Imported Upstream version 1.0.5.patch2
authorIOhannes m zmölnig <zmoelnig@umlaeute.mur.at>
Thu, 25 Nov 2010 14:09:54 +0000 (15:09 +0100)
committerIOhannes m zmölnig <zmoelnig@umlaeute.mur.at>
Thu, 25 Nov 2010 14:09:54 +0000 (15:09 +0100)
63 files changed:
CHANGESLOG.txt [new file with mode: 0644]
INSTALL.txt [new file with mode: 0644]
TODO.txt [new file with mode: 0644]
documentation/documentation.cpp [new file with mode: 0644]
documentation/html_footer.html [new file with mode: 0644]
documentation/img/jack_main_settings.jpg [new file with mode: 0644]
documentation/img/jack_routing.png [new file with mode: 0644]
documentation/img/qjackctl.png [new file with mode: 0644]
faust-src/Makefile [new file with mode: 0644]
faust-src/Makefile.compile [new file with mode: 0644]
faust-src/Makefile.ladspacompile [new file with mode: 0644]
faust-src/Makefile.mspcompile [new file with mode: 0644]
faust-src/Makefile.pdcompile [new file with mode: 0644]
faust-src/Makefile.qcompile [new file with mode: 0644]
faust-src/Makefile.qtcompile [new file with mode: 0644]
faust-src/Makefile.sccompile [new file with mode: 0644]
faust-src/Makefile.svg [new file with mode: 0644]
faust-src/Makefile.vstcompile [new file with mode: 0644]
faust-src/minimal.cpp [new file with mode: 0644]
faust-src/net-ks.dsp [new file with mode: 0644]
jacktrip_doxygen [new file with mode: 0644]
src/DataProtocol.cpp [new file with mode: 0644]
src/DataProtocol.h [new file with mode: 0644]
src/DataProtocolPOSIX.cpp.tmp [new file with mode: 0644]
src/DataProtocolPOSIX.h.tmp [new file with mode: 0644]
src/JackAudioInterface.cpp [new file with mode: 0644]
src/JackAudioInterface.h [new file with mode: 0644]
src/JackTrip.cpp [new file with mode: 0644]
src/JackTrip.h [new file with mode: 0644]
src/JackTripThread.cpp [new file with mode: 0644]
src/JackTripThread.h [new file with mode: 0644]
src/JackTripWorker.cpp [new file with mode: 0644]
src/JackTripWorker.h [new file with mode: 0644]
src/JackTripWorkerMessages.h [new file with mode: 0644]
src/LoopBack.cpp [new file with mode: 0644]
src/LoopBack.h [new file with mode: 0644]
src/NetKS.h [new file with mode: 0644]
src/PacketHeader.cpp [new file with mode: 0644]
src/PacketHeader.h [new file with mode: 0644]
src/ProcessPlugin.cpp [new file with mode: 0644]
src/ProcessPlugin.h [new file with mode: 0644]
src/RingBuffer.cpp [new file with mode: 0644]
src/RingBuffer.h [new file with mode: 0644]
src/RingBufferWavetable.h [new file with mode: 0644]
src/Settings.cpp [new file with mode: 0644]
src/Settings.h [new file with mode: 0644]
src/TestRingBuffer.h [new file with mode: 0644]
src/ThreadPoolTest.h [new file with mode: 0644]
src/UdpDataProtocol.cpp [new file with mode: 0644]
src/UdpDataProtocol.h [new file with mode: 0644]
src/UdpDataProtocolPOSIX.cpp.tmp [new file with mode: 0644]
src/UdpDataProtocolPOSIX.h.tmp [new file with mode: 0644]
src/UdpMasterListener.cpp [new file with mode: 0644]
src/UdpMasterListener.h [new file with mode: 0644]
src/build [new file with mode: 0755]
src/jacktrip-1.0.5.diff [new file with mode: 0644]
src/jacktrip.pro [new file with mode: 0644]
src/jacktrip_globals.cpp [new file with mode: 0644]
src/jacktrip_globals.h [new file with mode: 0644]
src/jacktrip_main.cpp [new file with mode: 0644]
src/jacktrip_tests.cpp [new file with mode: 0644]
src/jacktrip_types.h [new file with mode: 0644]
src/tests.cpp [new file with mode: 0644]

diff --git a/CHANGESLOG.txt b/CHANGESLOG.txt
new file mode 100644 (file)
index 0000000..1849861
--- /dev/null
@@ -0,0 +1,40 @@
+---
+1.0.5
+- (added) Compatibility with JamLink boxes (restricted at the moment to 48KHz, 64 buffer size and 1 channel)
+- (added) New port structure that allows the communication between a public server and a local client
+- (added) Option for packets without header
+- (added) Option to change default client name
+- (fixed) General optimizations and code cleanup
+- (added) Improved, now cross-platform build script
+
+---
+1.0.4
+- (fixed) Buss error caused when no physical inputs or outputs ports are available
+
+---
+1.0.3
+- (added) Redundancy Algorithm for UDP Packets to to avoid glitches with packet losses
+- (fixed) Now compiles on 64bits machines
+- (fixed) Improved exceptions handling
+- (added) Basic Karplus-Strong model added as Plug-in
+- (added) Some functionality reimplemented using signals and slots for 
+          more flexibility
+- (added) Multiple-Client-Server in alpha testing, expect it working in the next release
+
+---
+1.0.2 Alpha
+- (added) Port offset mode, to use a different UDP port than the default one.
+- (fixed) Improved thread behavior
+
+---
+1.0.1 Alpha
+- (added) jamlink mode to connect with jamlink boxes
+- (fixed) thread priority in both Linux and Mac OS X (still need some work on the Mac OS X version)
+- (fixed) Bug that was causing plug-ins not to behave correctly
+- (added) Loopback mode
+- (added) Underrun Modes: Wavetable (default) and set to zeros
+- (added) Check for peer audio settings, program exists if they don't match
+- (added) Automatically connect ports to available physical audio interface.
+
+---
+1.0 Alpha  - initial release
diff --git a/INSTALL.txt b/INSTALL.txt
new file mode 100644 (file)
index 0000000..cc95c0f
--- /dev/null
@@ -0,0 +1,69 @@
+Jacktrip : Build Instructions for Linux and MacOS X
+
+JackTrip: A System for High-Quality Audio Network Performance over the Internet.
+
+---
+MacOS X (10.3.9 or higher) Installation:
+
+If you are installing on MacOS X, a universal binary is provided.  You just need to have JackOSX installed on your machine
+http://www.jackosx.com/
+
+To install (using Terminal): go to bin/ directory and type:
+
+   sudo cp jacktrip /usr/bin/
+   (enter your password when prompted)
+
+   sudo chmod 755 /usr/bin/jacktrip
+   (now you can run jacktrip from any directory using Terminal)
+
+
+---
+Dependencies:
+
+You need to have installed the libraries in your system:
+qt4-devel
+jack-audio-connection-kit-devel
+
+If you are using yum (in Fedora 8 or later) you can just install them (as root) with:
+   yum install qt4-devel jack-audio-connection-kit-devel
+
+If you want to build on MacOS X, you need JackOSX
+http://www.jackosx.com/
+and Qt 4.5 or higher. 
+http://trolltech.com/products/qt/
+
+
+---
+Build:
+
+If you're on Mac OS X or Fedora Linux and have all the dependencies installed,
+you can build by simply going to the /src directory and typing the following:
+    ./build
+
+
+If the previous script doesn't work on a different Linux flavor, try building
+the Makfiles yourself. You'd need qmake (e.g., on Fedora, this command is called
+qmake-qt4). Then you can build by:
+    qmake jacktrip.pro
+    make release
+
+
+If you want to install install (using Terminal): on the /src directory type:
+
+   sudo cp jacktrip /usr/bin/
+   (enter your password when prompted)
+
+   sudo chmod 755 /usr/bin/jacktrip
+   (now you can run jacktrip from any directory using Terminal)
+
+
+---
+Post Configuration
+Detailed instructions at 
+http://ccrma.stanford.edu/groups/soundwire/software/jacktrip/
+
+
+---
+Using JackTrip
+Detailed instructions at 
+http://ccrma.stanford.edu/groups/soundwire/software/jacktrip/
diff --git a/TODO.txt b/TODO.txt
new file mode 100644 (file)
index 0000000..9b5e4d7
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,19 @@
+High Priority TODOS:
+--------------------
+
+- Add redundancy to UDP (DONE)
+- Finish header implementation, add run-time check
+
+
+Plug-ins:
+---------
+- Extend Plugin structure to include more than 1 plug-in and add the mode for local effect (not loopback)
+- add the offset option to process starting from a different channel
+- Set the faust compiler to automatically generate plugins
+- Add low latency compression www.celt-codec.org
+
+Protocol:
+---------
+- Add TCP clacc
+- Add SCTP class
+- Maybe add a layer of OSC communication for control messages
diff --git a/documentation/documentation.cpp b/documentation/documentation.cpp
new file mode 100644 (file)
index 0000000..54908c2
--- /dev/null
@@ -0,0 +1,124 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file documentation.cpp
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+
+// Main Page Documentation
+//-----------------------------------------------------------------
+/**
+\mainpage JackTrip Documentation
+    
+\section intro_sec About JackTrip
+
+JackTrip: A System for High-Quality Audio Network Performance
+over the Internet.
+
+JackTrip is a Linux and Mac OS X-based system used for multi-machine network
+performance over the Internet. It supports any number of channels
+(as many as the computer/network can handle) of bidirectional, high quality,
+uncompressed audio signal steaming.
+
+You can use it between any combination of Linux and Mac OS X
+(i.e., one end using Linux can connect to the other using Mac OS X).
+
+It is currently being developed and actively tested at CCRMA by the SoundWIRE group.
+
+
+
+\section install_sec Installation
+
+Download the latest release:
+<a href="https://sourceforge.net/project/showfiles.php?group_id=236811">Download</a>
+
+Please read the documentation inside the packet to install.
+
+\subsection install_subsec_osx Mac OS X Requirements
+
+You'll need: <a href="http://www.jackosx.com/">Jack OS X</a>.
+The documentation explains how to install it and set it up, and it's highly recommended.
+
+Jack OS X comes with JackPilot to do the audio routing.
+An alternative is <a href="http://qjackctl.sourceforge.net/">qjackctl</a>,
+which I find easier to use. You can find the binary here:
+<a href="http://www.ardour.org/osx_system_requirements">qjackctl mac binary</a>
+
+If you use Leopard, you won't need to configure the UDP ports manually.
+
+\subsubsection install_linux Linux Requirements
+
+Please read the documentation inside the packet to compile and install in linux.\n
+The older version of JackTrip is documented 
+<a href="http://ccrma.stanford.edu/groups/soundwire/software/jacktrip/">here</a>.
+Please follow those instructions to configure the firewall under 
+
+
+
+\section using Using JackTrip
+
+Type jacktrip in a terminal window to display a help list with all the options.
+JackTrip uses Jack as its audio server. You have to make sure that the settings in
+Jack are the same in the local and remote machine.
+
+There are two parameters that you want to tweak: Frames/Period and Sample Rate.
+The Lower the Frames/Period, the lower the latency.
+The higher the Sampling Rate, the higher the bandwidth requirements.
+You have to make sure these settings match in both machines. 
+
+\image html jack_main_settings.jpg
+
+You also may want to look at the internal buffering
+<tt>-q, --queue</tt> parameter in JackTrip. If your connection is very unstable, with a lot of jitter,
+you should increase this number at the expense of a higher latency.
+
+The audio bit resolution parameter, <tt>-b, --bitres</tt>, can be use to decrease (or increase)
+the bandwidth requirements, at the expense of a lower audio quality.
+
+A basic connection will have one of the nodes as a server:
+
+<tt>jacktrip -s</tt>
+
+And the other as a client
+
+<tt>jacktrip -c [SERVER-IP-NUMBER]</tt>
+
+You'll see a JackTrip client in Jack. Everything you connect into the send ports
+will be transmitted to your peer. You'll receive what your peer sends you on the receive ports. 
+
+\image html jack_routing.png
+
+*/
+
+
diff --git a/documentation/html_footer.html b/documentation/html_footer.html
new file mode 100644 (file)
index 0000000..979f8b8
--- /dev/null
@@ -0,0 +1,19 @@
+</BODY>
+</HTML>
+<center>
+<footer>
+<p>&nbsp</p>
+<font size="1">
+<p>Documentation generated by Doxygen $doxygenversion on $datetime</p>
+<p>
+&copy; 2008 by Juan-Pablo Caceres (jcaceres <em>at</em> ccrma <em>dot</em> stanford <em>dot</em> edu) and
+Chris Chafe<br />
+<a href="http://ccrma.stanford.edu/groups/soundwire/" title="SoundWIRE Group">SoundWIRE Group</a> at 
+<a href="http://ccrma.stanford.edu/" title="CCRMA home">CCRMA</a> - 
+<a href="http://www.stanford.edu/" title="Stanford home">Stanford University</a>
+</font>
+<p>
+<a href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=236811&amp;type=1" width="88" height="31" border="0" alt="SourceForge.net Logo" /></a>
+</p>
+</center>
+</footer>
diff --git a/documentation/img/jack_main_settings.jpg b/documentation/img/jack_main_settings.jpg
new file mode 100644 (file)
index 0000000..822fde7
Binary files /dev/null and b/documentation/img/jack_main_settings.jpg differ
diff --git a/documentation/img/jack_routing.png b/documentation/img/jack_routing.png
new file mode 100644 (file)
index 0000000..77e42e2
Binary files /dev/null and b/documentation/img/jack_routing.png differ
diff --git a/documentation/img/qjackctl.png b/documentation/img/qjackctl.png
new file mode 100644 (file)
index 0000000..afde566
Binary files /dev/null and b/documentation/img/qjackctl.png differ
diff --git a/faust-src/Makefile b/faust-src/Makefile
new file mode 100644 (file)
index 0000000..14ffe57
--- /dev/null
@@ -0,0 +1,99 @@
+all : jackgtk
+
+test: jackgtk alsagtk jackqt alsaqt ladspa ossgtk bench plot sndfile jackconsole
+
+svg:
+       $(MAKE) -f Makefile.svg
+       
+puredata :
+       install -d puredatadir
+       $(MAKE) DEST='puredatadir/' ARCH='puredata.cpp' LIB='' -f Makefile.pdcompile
+
+alsagtk :
+       install -d alsagtkdir
+       $(MAKE) DEST='alsagtkdir/' ARCH='alsa-gtk.cpp' LIB='-lpthread -lasound  `pkg-config --cflags --libs gtk+-2.0`' -f Makefile.compile
+
+jackgtk :
+       install -d jackgtkdir
+       $(MAKE) DEST='jackgtkdir/' ARCH='jack-gtk.cpp' LIB='`pkg-config --cflags --libs jack gtk+-2.0`' -f Makefile.compile
+
+jackqt :
+       install -d jackqtdir
+       $(MAKE) DEST='jackqtdir/' ARCH='jack-qt.cpp' LIB='-ljack' -f Makefile.qtcompile
+
+alsaqt :
+       install -d alsaqtdir
+       $(MAKE) DEST='alsaqtdir/' ARCH='alsa-qt.cpp' LIB='-lpthread -lasound' -f Makefile.qtcompile
+
+ladspa :
+       install -d ladspadir
+       $(MAKE) DEST='ladspadir/' ARCH='ladspa.cpp' LIB='-fPIC -shared' EXT='.so' -f Makefile.ladspacompile
+       
+jackwx :
+       install -d jackwxdir
+       $(MAKE) DEST='jackwxdir/' ARCH='jack-wx.cpp' LIB='`pkg-config jack  --cflags --libs` `wx-config --cflags --libs`' -f Makefile.compile
+
+ossgtk :
+       install -d ossgtkdir
+       $(MAKE) DEST='ossgtkdir/' ARCH='oss-gtk.cpp' LIB='-lpthread  `pkg-config gtk+-2.0  --cflags --libs`' -f Makefile.compile
+
+osswx :
+       install -d osswxdir
+       $(MAKE) DEST='osswxdir/' ARCH='oss-wx.cpp' LIB='-lpthread  `wx-config --cflags --libs`' -f Makefile.compile
+
+pagtk :
+       install -d pagtkdir
+       $(MAKE) DEST='pagtkdir/' ARCH='pa-gtk.cpp' LIB='-lpthread  -lportaudio `pkg-config gtk+-2.0  --cflags --libs`' -f Makefile.compile
+
+pawx :
+       install -d pawxdir
+       $(MAKE) DEST='pawxdir/' ARCH='pa-wx.cpp' LIB='-lpthread  -lportaudio `wx-config --cflags --libs`' -f Makefile.compile
+
+module :
+       install -d moduledir
+       $(MAKE) DEST='moduledir/' ARCH='module.cpp' LIB='-fPIC -shared' EXT='.so' -f Makefile.compile
+
+bundle :
+       install -d bundledir
+       $(MAKE) DEST='bundledir/' ARCH='module.cpp' LIB='-fPIC -bundle' EXT='.so' -f Makefile.compile
+
+msp :
+       install -d mspdir
+       $(MAKE) DEST='mspdir/' ARCH='max-msp.cpp' LIB='' -f Makefile.mspcompile
+
+vst :
+       install -d vstdir
+       $(MAKE) DEST='vstdir/' ARCH='vst.cpp' LIB='' -f Makefile.vstcompile
+
+bench :
+       install -d benchdir
+       $(MAKE) DEST='benchdir/' ARCH='bench.cpp' LIB='' -f Makefile.compile
+
+sndfile :
+       install -d sndfiledir
+       $(MAKE) DEST='sndfiledir/' ARCH='sndfile.cpp' LIB='-lsndfile' -f Makefile.compile
+
+plot :
+       install -d plotdir
+       $(MAKE) DEST='plotdir/' ARCH='plot.cpp' LIB='' -f Makefile.compile
+
+matlabplot :
+       install -d matlabplotdir
+       $(MAKE) DEST='matlabplotdir/' ARCH='matlabplot.cpp' LIB='' -f Makefile.compile
+
+q :
+       install -d qdir
+       $(MAKE) DEST='qdir/' ARCH='q.cpp' LIB='' -f Makefile.qcompile
+
+supercollider :
+       install -d supercolliderdir
+       $(MAKE) DEST='supercolliderdir/' ARCH='../architecture/supercollider.cpp' CXXFLAGS='`pkg-config --cflags libscsynth`' LIB='-fPIC -shared' EXT='.so' -f Makefile.sccompile
+
+jackconsole :
+       install -d jackconsoledir
+       $(MAKE) DEST='jackconsoledir/' ARCH='jack-console.cpp' LIB='`pkg-config --cflags --libs jack `' -f Makefile.compile
+
+clean :
+       rm -rf alsagtkdir jackgtkdir alsaqtdir jackqtdir vecalsagtkdir vecjackgtkdir ladspadir jackwxdir ossgtkdir osswxdir pagtkdir pawxdir moduledir bundledir mspdir vstdir benchdir sndfiledir plotdir benchdir supercolliderdir puredatadir qdir plotdir jackconsoledir matlabplotdir *-ps *-svg
+
+
diff --git a/faust-src/Makefile.compile b/faust-src/Makefile.compile
new file mode 100644 (file)
index 0000000..0681b10
--- /dev/null
@@ -0,0 +1,15 @@
+dspsrc  := $(wildcard *.dsp)
+cppsrc  := $(addprefix $(DEST), $(dspsrc:.dsp=.cpp))
+appl   := $(addprefix $(DEST), $(dspsrc:.dsp=$(EXT)))
+
+
+all :  $(appl)
+
+
+$(DEST)%$(EXT) : %.dsp 
+       faust $(VEC) -a $(ARCH) $< -o $@.cpp
+       $(CXX) -O3 $(CXXFLAGS) $(LIB) $@.cpp -o $@
+       
+
+clean :
+       rm -f $(DEST)
diff --git a/faust-src/Makefile.ladspacompile b/faust-src/Makefile.ladspacompile
new file mode 100644 (file)
index 0000000..f9d7ec5
--- /dev/null
@@ -0,0 +1,22 @@
+DEST   := ladspadir/
+dspsrc  := $(wildcard *.dsp)
+cppsrc  := $(addprefix $(DEST), $(dspsrc:.dsp=.cpp))
+modules        := $(addprefix $(DEST),  $(dspsrc:%.dsp=%.so))
+os     := $(shell uname)
+
+###allcpp: $(cppsrc)
+
+allmodules: $(modules)
+
+$(DEST)%.so: $(DEST)%.cpp
+ifeq ($(os), Darwin)
+       $(CXX) -fPIC -bundle -O3 $(CXXFLAGS) -Dmydsp=$(patsubst %.so,%,$(notdir $@)) $< -o $@
+else
+       $(CXX) -fPIC -shared -O3 $(CXXFLAGS) -Dmydsp=$(patsubst %.so,%,$(notdir $@)) $< -o $@
+endif
+
+$(DEST)%.cpp: %.dsp 
+       faust $(VEC) -a ladspa.cpp $< -o $@
+
+clean:
+       rm -rf $(DEST)
diff --git a/faust-src/Makefile.mspcompile b/faust-src/Makefile.mspcompile
new file mode 100644 (file)
index 0000000..6d1572d
--- /dev/null
@@ -0,0 +1,44 @@
+dspsrc  := $(wildcard *.dsp)
+cppsrc  := $(addprefix $(DEST), $(dspsrc:.dsp=.cpp))
+appl   := $(addprefix $(DEST), $(dspsrc:.dsp=~.mxo))
+processor := $(shell uname -p)
+
+INC    := -I/usr/local/include/c74support/max-includes -I/usr/local/include/c74support/msp-includes
+
+all :  $(appl)
+
+$(DEST)%~.mxo : %.dsp Info.plist.template
+       install -d $@/Contents/MacOS
+       faust $(VEC) -a $(ARCH) $< -o $@/$(<:.dsp=.cpp)
+ifeq ($(processor), i386)
+       g++ -arch i386 -fpascal-strings -fasm-blocks -g -O3 $(INC)  -c $@/$(<:.dsp=.cpp) -o $@/$(<:.dsp=.i386.o)
+       g++  -framework MaxAPI -framework Carbon -framework MaxAudioAPI -arch i386 -Wl,-Y,1455 -bundle $@/$(<:.dsp=.i386.o) -o $@/$(<:.dsp=.i386~) 
+       g++ -arch ppc -fpascal-strings -fasm-blocks -g -O3 $(INC)  -c $@/$(<:.dsp=.cpp) -o $@/$(<:.dsp=.ppc.o)
+       g++  -framework Carbon -framework MaxAPI -framework MaxAudioAPI -arch ppc -Wl,-Y,1455 -bundle $@/$(<:.dsp=.ppc.o) -o $@/$(<:.dsp=.ppc~)
+       sed s/FOO/$(<:.dsp=~)/ <Info.plist.template >$@/Contents/Info.plist
+       lipo -create $@/$(<:.dsp=.i386~) $@/$(<:.dsp=.ppc~) -output $@/Contents/MacOS/$(<:.dsp=~)
+       rm -f $@/$(<:.dsp=.ppc~) $@/$(<:.dsp=.ppc.o) $@/$(<:.dsp=.i386.o) $@/$(<:.dsp=.i386~)
+else
+       g++ -arch ppc -fpascal-strings -fasm-blocks -g -O3 $(INC)  -c $@/$(<:.dsp=.cpp) -o $@/$(<:.dsp=.ppc.o)
+       g++  -framework Carbon -framework MaxAPI -framework MaxAudioAPI -arch ppc -Wl,-Y,1455 -bundle $@/$(<:.dsp=.ppc.o) -o $@/$(<:.dsp=.ppc~)
+       sed s/FOO/$(<:.dsp=~)/ <Info.plist.template >$@/Contents/Info.plist
+       lipo -create $@/$(<:.dsp=.ppc~) -output $@/Contents/MacOS/$(<:.dsp=~)
+       rm -f $@/$(<:.dsp=.ppc~) $@/$(<:.dsp=.ppc.o)
+endif
+
+Info.plist.template :
+       echo '<?xml version="1.0" encoding="UTF-8"?>' > Info.plist.template
+       echo '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'  >> Info.plist.template
+       echo '<plist version="1.0">'            >> Info.plist.template
+       echo '<dict>'                           >> Info.plist.template
+       echo '  <key>CFBundleExecutable</key>'  >> Info.plist.template
+       echo '  <string>FOO</string>'           >> Info.plist.template
+       echo '  <key>CFBundleName</key>'        >> Info.plist.template
+       echo '  <string>FOO</string>'           >> Info.plist.template
+       echo '  <key>CFBundlePackageType</key>'  >> Info.plist.template
+       echo '  <string>iLaX</string>'          >> Info.plist.template
+       echo '</dict>'                          >> Info.plist.template
+       echo '</plist>'                         >> Info.plist.template
+
+clean :
+       rm -f $(DEST)
diff --git a/faust-src/Makefile.pdcompile b/faust-src/Makefile.pdcompile
new file mode 100644 (file)
index 0000000..c591c66
--- /dev/null
@@ -0,0 +1,45 @@
+DEST   := pddir/
+dspsrc  := $(wildcard *.dsp)
+cppsrc  := $(addprefix $(DEST), $(dspsrc:.dsp=.cpp))
+modules        := $(addprefix $(DEST),  $(dspsrc:.dsp=~.pd_linux))
+patches        := $(addprefix $(DEST),  $(dspsrc:.dsp=.pd))
+FAUST2PD := faust2pd
+F2PDFLAGS := -r 10 -s
+
+LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer -fPIC \
+    -Wall -W -Wshadow -Wno-unused -Wno-parentheses -Wno-switch $(CFLAGS)
+
+LINUXINCLUDE =
+
+
+###--------------------------------------------
+### Will use faust2pd to create the GUI patches
+### only if it is installed
+
+helper:=$(shell whereis faust2pd)
+
+ifeq ($(helper),faust2pd:)
+       todo:=$(modules)
+else
+       todo:=$(modules) $(patches)
+endif
+
+###--------------------------------------------
+
+
+allmodules: $(todo)
+
+$(DEST)%~.pd_linux: $(DEST)%.cpp
+       $(CXX) $(LINUXCFLAGS) $(LINUXINCLUDE) -shared -Dmydsp=$(patsubst %~.pd_linux,%,$(notdir $@)) $< -o $@
+
+$(DEST)%.cpp: %.dsp
+       faust -a $(ARCH) $< -o $@
+       
+$(DEST)%.pd: %.dsp
+       faust -xml $< -o /dev/null
+       $(FAUST2PD) $(F2PDFLAGS) $<.xml
+       mv $(<:.dsp=.pd) $(DEST)
+       rm -f $<.xml
+
+clean:
+       rm -rf $(DEST)
diff --git a/faust-src/Makefile.qcompile b/faust-src/Makefile.qcompile
new file mode 100644 (file)
index 0000000..9a12af2
--- /dev/null
@@ -0,0 +1,17 @@
+DEST   := qdir/
+dspsrc  := $(wildcard *.dsp)
+cppsrc  := $(addprefix $(DEST), $(dspsrc:.dsp=.cpp))
+modules        := $(addprefix $(DEST),  $(dspsrc:%.dsp=%.so))
+
+###allcpp: $(cppsrc)
+
+allmodules: $(modules)
+
+$(DEST)%.so: $(DEST)%.cpp
+       $(CXX) -shared -O3 $(CXXFLAGS) -Dmydsp=$(patsubst %.so,%,$(notdir $@)) $< -o $@
+
+$(DEST)%.cpp: %.dsp 
+       faust $(VEC) -a q.cpp $< -o $@
+
+clean:
+       rm -rf $(DEST)
diff --git a/faust-src/Makefile.qtcompile b/faust-src/Makefile.qtcompile
new file mode 100644 (file)
index 0000000..70d1018
--- /dev/null
@@ -0,0 +1,49 @@
+###--------------------------------------------
+### DEST : directory where to put binaries
+### ARCH : faust architecture file
+
+system := $(shell uname -s)
+dspsrc  := $(wildcard *.dsp)
+cppsrc  := $(addprefix $(DEST), $(dspsrc:.dsp=.cpp))
+
+
+### check what type of applications to build (MacOSX Darwin or Linux)
+ifeq ($(system), Darwin)
+appls  := $(addprefix $(DEST),  $(dspsrc:.dsp=.app))
+else
+appls  := $(addprefix $(DEST),  $(dspsrc:.dsp=))
+endif
+
+
+TMP = /var/tmp/$(<:.dsp=)
+###--------------------------------------------
+
+
+all : $(appls)
+
+
+### Darwin 
+$(DEST)%.app : %.dsp
+       rm -rf $(TMP)
+       install -d $(TMP)
+       faust -a $(ARCH) $< -o $(TMP)/$<.cpp
+       cd $(TMP); qmake -project "INCLUDEPATH+=/usr/local/lib/faust/" "LIBS+=$(LIB)" "HEADERS+=/usr/local/lib/faust/faustqt.h" 
+       cd $(TMP); qmake
+       cd $(TMP); xcodebuild -project $(<:.dsp=).xcodeproj
+       mv $(TMP)/build/Default/$(<:.dsp=.app) $@
+       rm -rf $(TMP)
+
+
+### Linux
+$(DEST)% : %.dsp
+       rm -rf $(TMP)
+       install -d $(TMP)
+       faust -a $(ARCH) $< -o $(TMP)/$<.cpp
+       cd $(TMP); qmake -project "INCLUDEPATH+=/usr/local/lib/faust/" "LIBS+=$(LIB)" "HEADERS+=/usr/local/lib/faust/faustqt.h" 
+       cd $(TMP); qmake 
+       make -C $(TMP)
+       mv $(TMP)/$(<:.dsp=) $@
+       rm -rf $(TMP)
+
+clean:
+       rm -rf $(DEST)
diff --git a/faust-src/Makefile.sccompile b/faust-src/Makefile.sccompile
new file mode 100644 (file)
index 0000000..628b2c8
--- /dev/null
@@ -0,0 +1,41 @@
+# Makefile to produce supercollider plugins with Faust
+#      'foo.dsp' -> 'foo.so' and 'foo.sc'
+#
+
+dspsrc         := $(wildcard *.dsp)
+scfiles                := $(addprefix $(DEST), $(dspsrc:.dsp=.sc))
+sofiles                := $(addprefix $(DEST), $(dspsrc:.dsp=.so))
+CXXFLAGS       := `pkg-config --cflags libscsynth` $(CXXFLAGS)
+LIB            := -shared
+
+
+###--------------------------------------------
+### Will use faust2sc to create the class file
+### only if it is installed
+
+helper:=$(shell whereis faust2sc)
+
+ifeq ($(helper),faust2sc:)
+       todo:=$(sofiles)
+else
+       todo:=$(sofiles) $(scfiles)
+endif
+
+
+###--------------------------------------------
+
+
+all : $(todo)
+
+$(DEST)%.cpp: %.dsp
+       faust -a $(ARCH) $< -o $@
+
+$(DEST)%.so: $(DEST)%.cpp
+       $(CXX) $(CXXFLAGS) $(OPTFLAGS) $(LIB) $< -o $@
+
+$(DEST)%.sc : %.dsp.xml
+       faust2sc --prefix=Faust $< --output=$@
+
+%.dsp.xml: %.dsp
+       faust --xml -o /dev/null $<
+
diff --git a/faust-src/Makefile.svg b/faust-src/Makefile.svg
new file mode 100644 (file)
index 0000000..fd271fe
--- /dev/null
@@ -0,0 +1,12 @@
+src    := $(wildcard *.dsp)
+target         := $(src:.dsp=.dsp-svg)
+
+all :  $(target)
+
+
+%.dsp-svg : %.dsp
+       faust -svg $< > /dev/null
+       
+
+clean :
+       rm -rf $(target)
diff --git a/faust-src/Makefile.vstcompile b/faust-src/Makefile.vstcompile
new file mode 100644 (file)
index 0000000..658a69b
--- /dev/null
@@ -0,0 +1,31 @@
+dspsrc  := $(wildcard *.dsp)
+cppsrc  := $(addprefix $(DEST), $(dspsrc:.dsp=.cpp))
+appl   := $(addprefix $(DEST), $(dspsrc:.dsp=$(EXT)))
+
+# Setup this variable to access the VST SDK files
+vst_sdk := "/Volumes/Document1/Developpement/ProjectsCVS/JackCVS/JackOSX/jackosx/jackplugins/JACK-ASinsert/VST/VSTSDK"
+
+# Setup this variable with the location for the compiled VST plug-ins
+install_plug_ins := "/Library/Audio/Plug-Ins/VST"
+
+all :  $(appl)
+
+       
+$(DEST)% : %.dsp
+       install -d $@
+       cp -r $(vst_sdk) $@
+       cp -r /usr/local/lib/faust/VST/* $@
+       faust $(VEC) -a $(ARCH) $< -o $@/vst-output.cpp
+       mv  $@/vst-output.cpp  $@/$(<:.dsp=.cpp)
+       sed -e 's/vst-output.cpp/$(<:.dsp=.cpp)/'  $@/VST.xcode/project.pbxproj > $@/VST.xcode/new_project.pbxproj &&  mv $@/VST.xcode/new_project.pbxproj $@/VST.xcode/project.pbxproj
+       sed -e 's/XXXX/$(<:.dsp=)/'  $@/Info.plist  >  $@/new_Info.plist  &&  mv $@/new_Info.plist $@/Info.plist
+       xcodebuild -project $@/VST.xcode clean
+       xcodebuild -project $@/VST.xcode
+       mv $@/build/FaustVST.vst $@/build/$(<:.dsp=.vst)
+       rm -r $@/build/VST.build
+       install -d $(install_plug_ins)
+       cp -r $@/build/$(<:.dsp=.vst) $(install_plug_ins)
+       
+
+clean :
+       rm -f $(DEST)
diff --git a/faust-src/minimal.cpp b/faust-src/minimal.cpp
new file mode 100644 (file)
index 0000000..2d1222a
--- /dev/null
@@ -0,0 +1,97 @@
+#ifdef __GNUC__
+
+#define max(x,y) (((x)>(y)) ? (x) : (y))
+#define min(x,y) (((x)<(y)) ? (x) : (y))
+
+// abs is now predefined
+//template<typename T> T abs (T a)                     { return (a<T(0)) ? -a : a; }
+
+
+inline int             lsr (int x, int n)                      { return int(((unsigned int)x) >> n); }
+
+/******************************************************************************
+*******************************************************************************
+
+                                                              VECTOR INTRINSICS
+
+*******************************************************************************
+*******************************************************************************/
+
+//inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
+inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
+
+<<includeIntrinsic>>
+
+/******************************************************************************
+*******************************************************************************
+
+                       ABSTRACT USER INTERFACE
+
+*******************************************************************************
+*******************************************************************************/
+
+class UI
+{
+       bool    fStopped;
+public:
+               
+       UI() : fStopped(false) {}
+       virtual ~UI() {}
+       
+       virtual void addButton(char* label, float* zone) = 0;
+       virtual void addToggleButton(char* label, float* zone) = 0;
+       virtual void addCheckButton(char* label, float* zone) = 0;
+       virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
+       virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
+       virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step) = 0;
+       
+       virtual void openFrameBox(char* label) = 0;
+       virtual void openTabBox(char* label) = 0;
+       virtual void openHorizontalBox(char* label) = 0;
+       virtual void openVerticalBox(char* label) = 0;
+       virtual void closeBox() = 0;
+       
+       virtual void run() = 0;
+       
+       void stop()     { fStopped = true; }
+       bool stopped()  { return fStopped; }
+};
+
+
+
+
+/******************************************************************************
+*******************************************************************************
+
+                           FAUST DSP
+
+*******************************************************************************
+*******************************************************************************/
+
+
+
+//----------------------------------------------------------------
+//  abstract definition of a signal processor
+//----------------------------------------------------------------
+                       
+class dsp {
+ protected:
+       int fSamplingFreq;
+ public:
+       dsp() {}
+       virtual ~dsp() {}
+
+       virtual int getNumInputs()                                              = 0;
+       virtual int getNumOutputs()                                     = 0;
+       virtual void buildUserInterface(UI* interface)  = 0;
+       virtual void init(int samplingRate)                     = 0;
+       virtual void compute(int len, float** inputs, float** outputs)  = 0;
+};
+               
+
+//----------------------------------------------------------------------------
+//  FAUST generated signal processor
+//----------------------------------------------------------------------------
+               
+
+<<includeclass>>
diff --git a/faust-src/net-ks.dsp b/faust-src/net-ks.dsp
new file mode 100644 (file)
index 0000000..858749a
--- /dev/null
@@ -0,0 +1,29 @@
+declare name        "net-ks";
+declare version     "1.0";
+declare author      "Juan-Pablo Caceres";
+declare license     "MIT";
+declare copyright   "(c) Juan-Pablo Caceres 2008";
+
+//-----------------------------------------------------
+//              Network-karplus-strong,
+//              Based on 'karplus' from Faust Examples
+//-----------------------------------------------------
+
+import("music.lib");
+
+// Excitation
+//-----------
+upfront(x)  = (x-x') > 0.0;
+decay(n,x)  = x - (x>0.0)/n;
+release(n)  = + ~ decay(n);
+trigger(n)  = upfront : release(n) : >(0.0);
+
+// Filters
+//--------
+// Average LowPass Filter
+av_lowpass(x)  = (x+x')/2;
+
+process = _ , 
+       ( noise * 0.9 :
+        vgroup("excitator", *(button("play") : trigger(300))) ) 
+        :> av_lowpass;
diff --git a/jacktrip_doxygen b/jacktrip_doxygen
new file mode 100644 (file)
index 0000000..61e6740
--- /dev/null
@@ -0,0 +1,1418 @@
+# Doxyfile 1.5.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = JackTrip
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ./WWW/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, 
+# and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ./src ./documentation
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = ./documentation/img
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = ./documentation/html_footer.html
+
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hiererachy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW      = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = Sans
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is enabled by default, which results in a transparent 
+# background. Warning: Depending on the platform used, enabling this option 
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they 
+# become hard to read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/src/DataProtocol.cpp b/src/DataProtocol.cpp
new file mode 100644 (file)
index 0000000..3168a5f
--- /dev/null
@@ -0,0 +1,61 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file DataProtocol.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#include "DataProtocol.h"
+#include "jacktrip_globals.h"
+#include "JackTrip.h"
+
+#include <iostream>
+#include <cstdlib>
+
+#include <QHostInfo>
+#include <QHostAddress>
+
+using std::cout; using std::endl;
+
+
+//*******************************************************************************
+DataProtocol::DataProtocol(JackTrip* jacktrip,
+                          const runModeT runmode,
+         int /*bind_port*/, int /*peer_port*/) :
+  mStopped(false), mHasPacketsToReceive(false), mRunMode(runmode), mJackTrip(jacktrip)
+{}
+
+
+//*******************************************************************************
+DataProtocol::~DataProtocol()
+{}
diff --git a/src/DataProtocol.h b/src/DataProtocol.h
new file mode 100644 (file)
index 0000000..9f9d2bc
--- /dev/null
@@ -0,0 +1,191 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file DataProtocol.h
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#ifndef __DATAPROTOCOL_H__
+#define __DATAPROTOCOL_H__
+
+//#include <sys/socket.h> //basic socket definitions
+#include <netinet/in.h> //sockaddr_in{} and other Internet defns
+#include <arpa/inet.h> //inet(3) functions
+#include <netdb.h>
+#include <tr1/memory> //for shared_ptr
+
+#include <QThread>
+#include <QHostAddress>
+
+class JackTrip; // forward declaration
+
+
+/** \brief Base class that defines the transmission protocol.
+ * 
+ * This base class defines most of the common method to setup and connect
+ * sockets using the individual protocols (UDP, TCP, SCTP, etc).
+ *
+ * The class has to be constructed using one of two modes (runModeT):\n
+ * - SENDER
+ * - RECEIVER
+ *
+ * This has to be specified as a constructor argument. When using, create two instances
+ * of the class, one to receive and one to send packets. Each instance will run on a
+ * separate thread.
+ *
+ * Redundancy and forward error correction should be implemented on each
+ * Transport protocol, cause they depend on the protocol itself
+ *
+ * \todo This Class should contain definition of jacktrip header and basic funcionality to obtain
+ * local machine IPs and maybe functions to manipulate IPs.
+ * Redundancy and forward error correction should be implemented on each
+ * Transport protocol, cause they depend on the protocol itself
+ *
+ * \todo The transport protocol itself has to be implemented subclassing this class, i.e.,
+ * using a TCP or UDP protocol.
+ *
+ * Even if the underlined transmission protocol is stream oriented (as in TCP),
+ * we send packets that are the size of the audio processing buffer.
+ * Use AudioInterface::getBufferSize to obtain this value.
+ *
+ * Each transmission (i.e., inputs and outputs) run on its own thread.
+ */
+class DataProtocol : public QThread
+{
+public:
+
+  //----------ENUMS------------------------------------------
+  /// \brief Enum to define packet header types
+  enum packetHeaderTypeT {
+    DEFAULT, ///< Default application header
+    JAMLINK, ///< Header to use with Jamlinks
+    EMPTY    ///< Empty Header
+  };
+
+  /// \brief Enum to define class modes, SENDER or RECEIVER
+  enum runModeT {
+    SENDER, ///< Set class as a Sender (send packets)
+    RECEIVER ///< Set class as a Receiver (receives packets)
+  };
+  //---------------------------------------------------------
+
+
+  /** \brief The class constructor 
+   * \param jacktrip Pointer to the JackTrip class that connects all classes (mediator)
+   * \param runmode Sets the run mode, use either DataProtocol::SENDER or
+   * DataProtocol::RECEIVER
+   * \param headertype packetHeaderTypeT header type to use for packets
+   * \param bind_port Port number to bind for this socket (this is the receive or send port depending on the runmode)
+   * \param peer_port Peer port number (this is the receive or send port depending on the runmode)
+   */
+  DataProtocol(JackTrip* jacktrip,
+              const runModeT runmode,
+              int bind_port, int peer_port);
+  
+  /// \brief The class destructor
+  virtual ~DataProtocol();
+  
+  /** \brief Implements the thread loop
+   *
+   * Depending on the runmode, with will run a DataProtocol::SENDER thread or
+   * DataProtocol::RECEIVER thread
+   */
+  virtual void run() = 0;
+
+  /// \brief Stops the execution of the Thread
+  virtual void stop() { mStopped = true; };
+
+  /** \brief Sets the size of the audio part of the packets
+   * \param size_bytes Size in bytes
+   */
+  void setAudioPacketSize(const size_t size_bytes){ mAudioPacketSize = size_bytes; };
+
+  /** \brief Get the size of the audio part of the packets
+   * \return size_bytes Size in bytes
+   */
+  size_t getAudioPacketSizeInBites() { return(mAudioPacketSize); };
+
+  /** \brief Set the peer address
+   * \param peerHostOrIP IPv4 number or host name
+   * \todo implement here instead of in the subclass UDP
+   */
+  virtual void setPeerAddress(const char* peerHostOrIP) = 0;
+
+  /** \brief Set the peer incomming (receiving) port number
+   * \param port Port number
+   * \todo implement here instead of in the subclass UDP
+   */
+  virtual void setPeerPort(int port) = 0;
+
+  //virtual void getPeerAddressFromFirstPacket(QHostAddress& peerHostAddress,
+  //                                uint16_t& port) = 0;
+
+protected:
+
+  /** \brief Get the Run Mode of the object
+   * \return SENDER or RECEIVER
+   */
+  runModeT getRunMode() const { return mRunMode; };
+
+  /// Boolean stop the execution of the thread
+  volatile bool mStopped;
+  /// Boolean to indicate if the RECEIVER is waiting to obtain peer address
+  volatile bool mHasPeerAddress;
+  /// Boolean that indicates if a packet was received
+  volatile bool mHasPacketsToReceive;
+
+
+private:
+
+  int mLocalPort; ///< Local Port number to Bind
+  int mPeerPort; ///< Peer Port number to Bind
+  const runModeT mRunMode; ///< Run mode, either SENDER or RECEIVER
+  
+  struct sockaddr_in mLocalIPv4Addr; ///< Local IPv4 Address struct
+  struct sockaddr_in mPeerIPv4Addr; ///< Peer IPv4 Address struct
+  
+  /// Number of clients running to check for ports already used
+  /// \note Unimplemented, try to find another way to check for used ports
+  static int sClientsRunning;
+  
+  size_t mAudioPacketSize; ///< Packet audio part size
+
+
+  /// \todo check a better way to access the header from the subclasses
+protected:
+  //PacketHeader* mHeader; ///< Packet Header
+  JackTrip* mJackTrip; ///< JackTrip mediator class
+
+};
+
+#endif
diff --git a/src/DataProtocolPOSIX.cpp.tmp b/src/DataProtocolPOSIX.cpp.tmp
new file mode 100644 (file)
index 0000000..b92459c
--- /dev/null
@@ -0,0 +1,222 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file DataProtocol.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#include "DataProtocol.h"
+#include "jacktrip_globals.h"
+#include "JackAudioInterface.h"
+#include "PacketHeader.h"
+
+#include <iostream>
+#include <cstdlib>
+
+#include <QHostInfo>
+#include <QHostAddress>
+
+using std::cout; using std::endl;
+
+//*******************************************************************************
+DataProtocol::DataProtocol(const runModeT runmode,
+                          const packetHeaderTypeT headertype) : 
+  mRunMode(runmode), mStopped(false), mHasPacketsToReceive(false), mHeader(NULL)
+{
+  //--------PROTOTYPE-------------------------
+  if ( headertype == DEFAULT ) {
+    mHeader = new DefaultHeader;
+  }
+  else if ( headertype == JAMLINK ) {
+    mHeader = new JamLinkHeader;
+  }
+  //------------------------------------------
+
+  // Base ports gInputPort_0 and gOutputPort_0defined at globals.h
+  if (mRunMode == RECEIVER) {
+    mLocalPort = gInputPort_0;
+    mPeerPort = gOutputPort_0;
+  }
+  else if (mRunMode == SENDER) {
+    mLocalPort = gOutputPort_0;
+    mPeerPort = gInputPort_0;
+  }
+
+  this->setLocalIPv4Address();
+}
+
+
+//*******************************************************************************
+DataProtocol::~DataProtocol()
+{
+  delete mHeader;
+}
+
+
+//*******************************************************************************
+void DataProtocol::stop()
+{
+  mStopped = true;
+}
+
+
+//*******************************************************************************
+void DataProtocol::setLocalIPv4Address()
+{
+  bzero(&mLocalIPv4Addr, sizeof(mLocalIPv4Addr));
+  mLocalIPv4Addr.sin_family = AF_INET;//AF_INET: IPv4 Protocol
+  mLocalIPv4Addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY: let the kernel decide the active address
+  mLocalIPv4Addr.sin_port = htons(mLocalPort);//set local port
+  //std::cout << "mLocalPort = " << mLocalPort << std::endl;
+}
+
+
+//*******************************************************************************
+void DataProtocol::setPeerIPv4Address(const char* peerHostOrIP)
+{
+  const char* peerAddress; // dotted decimal address to use in the struct below
+
+  /// \todo Improve this to make it work also with local ip numbers, in a LAN,
+  /// that don't have an assigned host name
+  /*
+  // Resolve Peer IPv4 with either doted integer IP or hostname
+  //----------------------------------------------------------
+  std::cout << "Resolving Peer IPv4 address..." << std::endl;
+  QHostInfo info = QHostInfo::fromName(peerHostOrIP);
+  if ( !info.addresses().isEmpty() ) {
+    std::cout << "Peer Address Found" << std::endl;
+    QHostAddress address = info.addresses().first(); // use the first address in list
+    peerAddress = address.toString().toLatin1();
+  }
+  else {
+    std::cerr << "ERROR: Could not set Peer IP Address" << std::endl;
+    std::cerr << "Check that it's public or that the hostname exists" << std::endl;
+    std::exit(1);
+  }
+  */
+
+  // temporary implementation to make this work
+  /// \todo change this
+  peerAddress = peerHostOrIP;
+
+  // Set the Peer IPv4 Address struct
+  //---------------------------------
+  bzero(&mPeerIPv4Addr, sizeof(mPeerIPv4Addr));
+  mPeerIPv4Addr.sin_family = AF_INET;//AF_INET: IPv4 Protocol
+  mPeerIPv4Addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY: let the kernel decide the active address
+  mPeerIPv4Addr.sin_port = htons(mPeerPort);//set Peer port
+  //std::cout << "mPeerPort = " << mPeerPort << std::endl;
+  int nPeer = inet_pton(AF_INET, peerAddress, &mPeerIPv4Addr.sin_addr);
+  if ( nPeer == 1 ) {
+    std::cout << "Successful Set Peer Address" << std::endl;
+  }
+  else if ( nPeer == 0 ) {
+    std::cout << "Error: Incorrect presentation format for address" << std::endl;
+    std::exit(1);
+  }
+  else {
+    std::cout << "Error: Could not set Peer Address" << std::endl;
+    std::exit(1);
+  }
+
+}
+
+
+//*******************************************************************************
+void DataProtocol::setRingBuffer(std::tr1::shared_ptr<RingBuffer> RingBuffer)
+{
+  mRingBuffer = RingBuffer;
+}
+
+
+//*******************************************************************************
+void DataProtocol::run()
+{
+  std::cout << "Running DataProtocol Thread" << std::endl;
+  std::cout << gPrintSeparator << std::endl;
+  size_t packet_size = getAudioPacketSize();
+  int8_t packet[packet_size];
+  
+  switch ( mRunMode ) 
+    {
+    case RECEIVER : 
+      //----------------------------------------------------------------------------------- 
+      // Wait for the first packet to be ready and obtain address
+      // from that packet
+      /// \todo here is the place to read the datagram and check if the settings match
+      /// the local ones. Extract this information from the header
+      std::cout << "Waiting for Peer..." << std::endl;
+      this->receivePacket( (char*) packet, packet_size); // This blocks waiting for the first packet
+      std::cout << "Received Connection for Peer!" << std::endl;
+
+      while ( !mStopped )
+       {
+         //std::cout << "RECEIVING PACKETS" << std::endl;
+         /// \todo Set a timer to report packats arriving too late
+         //std::cout << "RECIEVING THREAD" << std::endl;
+         
+         this->receivePacket( (char*) packet, packet_size);
+         /// \todo Change this to match buffer size
+         //std::cout << "PACKET RECIEVED" << std::endl;
+         mRingBuffer->insertSlotBlocking(packet);
+         //std::cout << buf << std::endl;
+       }
+      break;
+      
+      
+    case SENDER : 
+      //----------------------------------------------------------------------------------- 
+      while ( !mStopped )
+       {
+         //std::cout << "SENDING PACKETS --------------------------" << std::endl;
+         /// \todo This should be blocking, since we don't want to send trash
+         mRingBuffer->readSlotBlocking(packet);
+         //std::cout << "SENDING PACKETS" << std::endl;
+         this->sendPacket( (char*) packet, packet_size);
+         //std::cout << "SENDING PACKETS DONE!!!" << std::endl;
+         //this->sendPacket( sendtest, 64);
+       }
+      break;
+    }
+}
+
+void DataProtocol::setAudioPacketSize(size_t size_bytes)
+{
+  mAudioPacketSize = size_bytes;
+}
+
+
+size_t DataProtocol::getAudioPacketSize()
+{
+  return(mAudioPacketSize);
+}
diff --git a/src/DataProtocolPOSIX.h.tmp b/src/DataProtocolPOSIX.h.tmp
new file mode 100644 (file)
index 0000000..c812d02
--- /dev/null
@@ -0,0 +1,213 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file DataProtocol.h
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#ifndef __DATAPROTOCOL_H__
+#define __DATAPROTOCOL_H__
+
+//#include <sys/socket.h> //basic socket definitions
+#include <netinet/in.h> //sockaddr_in{} and other Internet defns
+#include <arpa/inet.h> //inet(3) functions
+#include <netdb.h>
+#include <tr1/memory> //for shared_ptr
+
+#include <QThread>
+
+#include "RingBuffer.h"
+//#include "PacketHeader.h"
+class PacketHeader; // forward declaration
+
+
+/** \brief Base class that defines the transmission protocol.
+ * 
+ * This base class defines most of the common method to setup and connect
+ * sockets using the individual protocols (UDP, TCP, SCTP, etc).
+ *
+ * The class has to be constructed using one of two modes (runModeT):\n
+ * - SENDER
+ * - RECEIVER
+ *
+ * This has to be specified as a constructor argument. When using, create two instances
+ * of the class, one to receive and one to send packets. Each instance will run on a
+ * separate thread.
+ *
+ * Redundancy and forward error correction should be implemented on each
+ * Transport protocol, cause they depend on the protocol itself
+ *
+ * \todo This Class should contain definition of jacktrip header and basic funcionality to obtain
+ * local machine IPs and maybe functions to manipulate IPs.
+ * Redundancy and forward error correction should be implemented on each
+ * Transport protocol, cause they depend on the protocol itself
+ *
+ * \todo The transport protocol itself has to be implemented subclassing this class, i.e.,
+ * using a TCP or UDP protocol.
+ *
+ * Even if the underlined transmission protocol is stream oriented (as in TCP),
+ * we send packets that are the size of the audio processing buffer.
+ * Use AudioInterface::getBufferSize to obtain this value.
+ *
+ * Each transmission (i.e., inputs and outputs) run on its own thread.
+ */
+class DataProtocol : public QThread
+{
+public:
+
+  /// \brief Enum to define packet header types
+  enum packetHeaderTypeT {
+    DEFAULT, ///< Default application header
+    JAMLINK ///< Header to use with Jamlinks
+  };
+
+  /// \brief Enum to define class modes, SENDER or RECEIVER
+  enum runModeT {
+    SENDER, ///< Set class as a Sender (send packets)
+    RECEIVER ///< Set class as a Receiver (receives packets)
+  };
+  
+
+  /** \brief The class constructor 
+   * \param runmode Sets the run mode, use either SENDER or RECEIVER
+   */
+  DataProtocol(const runModeT runmode,
+              const packetHeaderTypeT headertype = DEFAULT);
+  
+  /// \brief The class destructor
+  virtual ~DataProtocol();
+  
+  /** \brief Sets the peer (remote) IPv4 address struct
+   * \param peerHostOrIP Either an IPv4 dotted integer number or a hostname
+   */
+  virtual void setPeerIPv4Address(const char* peerHostOrIP);
+
+  /** \brief Receive a packet from the UDPSocket
+   *
+   * This method has to be implemented in the sub-classes
+   * \param buf Location at which to store the buffer
+   * \param n size of packet to receive in bytes
+   * \return number of bytes read, -1 on error
+   */
+  virtual size_t receivePacket(char* buf, size_t n) = 0;
+  /** \brief Sends a packet
+   *
+   * This method has to be implemented in the sub-classes
+   * \param buff Buffer to send
+   * \param n size of packet to receive in bytes
+   * \return number of bytes read, -1 on error
+   */
+  virtual size_t sendPacket(const char* buff, size_t n) = 0;
+
+  /** \brief Implements the thread loop
+   *
+   * Depending on the runmode, with will run a RECEIVE thread or
+   * SEND thread
+   */
+  virtual void run();
+
+  /** \brief Set the pointer to the RingBuffer that'll be use to read 
+   * or write
+   */
+  void setRingBuffer(std::tr1::shared_ptr<RingBuffer> RingBuffer);
+
+  /// \brief Stops the execution of the Thread
+  void stop();
+
+  /** \brief Sets the size of the audio part of the packets
+   * \param size_bytes Size in bytes
+   */
+  void setAudioPacketSize(size_t size_bytes);
+
+  /** \brief Get the size of the audio part of the packets
+   * \return size_bytes Size in bytes
+   */
+  size_t getAudioPacketSize();
+
+  //virtual void getIPAddressFromFirstPacket() = 0;
+
+
+protected:
+
+  /** \brief Sets the local IPv4 address struct
+   *
+   * It uses the default active device.
+   */
+  virtual void setLocalIPv4Address();
+
+  /** \brief Get the Run Mode of the object
+   * \return SENDER or RECEIVER
+   */
+  runModeT getRunMode() const { return mRunMode; };
+
+  /** \brief Returns the Local machine IPv4 socket address stuct
+   * \return Socket address stuct
+   */
+  const sockaddr_in& getLocalIPv4AddressStruct() const { return mLocalIPv4Addr; };
+  
+  /** \brief Returns the Peer  IPv4 socket address stuct
+   * \return Socket address stuct
+   */
+  const sockaddr_in& getPeerIPv4AddressStruct() const { return mPeerIPv4Addr; };
+
+
+private:
+
+  int mLocalPort; ///< Local Port number to Bind
+  int mPeerPort; ///< Peer Port number to Bind
+  const runModeT mRunMode; ///< Run mode, either SENDER or RECEIVER
+
+  struct sockaddr_in mLocalIPv4Addr; ///< Local IPv4 Address struct
+  struct sockaddr_in mPeerIPv4Addr; ///< Peer IPv4 Address struct
+
+  /// Smart Pointer to RingBuffer to read (for SENDER) or write (for RECEIVER)
+  std::tr1::shared_ptr<RingBuffer> mRingBuffer; 
+  
+  /// Boolean stop the execution of the thread
+  volatile bool mStopped;
+  /// Boolean to indicate if the RECEIVER is waiting to obtain peer address
+  volatile bool mHasPeerAddress;
+  /// Boolean that indicates if a packet was received
+  volatile bool mHasPacketsToReceive;
+
+  /// Number of clients running to check for ports already used
+  /// \note Unimplemented, try to find another way to check for used ports
+  static int sClientsRunning;
+
+  size_t mAudioPacketSize; ///< Packet audio part size
+
+  PacketHeader* mHeader; ///< Packet Header
+};
+
+#endif
diff --git a/src/JackAudioInterface.cpp b/src/JackAudioInterface.cpp
new file mode 100644 (file)
index 0000000..5ca3ba3
--- /dev/null
@@ -0,0 +1,675 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackAudioInterface.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#include "JackAudioInterface.h"
+#include "jacktrip_globals.h"
+#include "JackTrip.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <cmath>
+#include <stdexcept>
+
+///************PROTORYPE FOR CELT**************************
+//#include <celt/celt.h>
+//#include <celt/celt_header.h>
+//#include <celt/celt_types.h>
+///********************************************************
+
+#include <QTextStream>
+#include <QMutexLocker>
+
+using std::cout; using std::endl;
+
+
+// sJackMutex definition
+QMutex JackAudioInterface::sJackMutex;
+
+
+//*******************************************************************************
+JackAudioInterface::JackAudioInterface(JackTrip* jacktrip,
+                                      int NumInChans, int NumOutChans,
+               audioBitResolutionT AudioBitResolution,
+               const char* ClienName) :
+  mNumInChans(NumInChans), mNumOutChans(NumOutChans), 
+  mAudioBitResolution(AudioBitResolution*8), mBitResolutionMode(AudioBitResolution),
+  mClient(NULL),
+  mClientName(ClienName),
+  mJackTrip(jacktrip)
+{
+  //setupClient();
+  //setProcessCallback();
+}
+
+
+//*******************************************************************************
+JackAudioInterface::~JackAudioInterface()
+{
+  delete[] mInputPacket;
+  delete[] mOutputPacket;
+
+  for (int i = 0; i < mNumInChans; i++) {
+    delete[] mInProcessBuffer[i];
+  }
+
+  for (int i = 0; i < mNumOutChans; i++) {
+    delete[] mOutProcessBuffer[i];
+  }
+}
+
+
+//*******************************************************************************
+void JackAudioInterface::setup()
+{
+  setupClient();
+  setProcessCallback();
+}
+
+
+//*******************************************************************************
+void JackAudioInterface::setupClient()
+{
+  const char* client_name = mClientName;
+  const char* server_name = NULL;
+  jack_options_t options = JackNoStartServer;
+  jack_status_t status;
+
+  // Try to connect to the server
+  /// \todo Write better warning messages. This following line displays very
+  /// verbose message, check how to desable them.
+  {
+    QMutexLocker locker(&sJackMutex);
+    mClient = jack_client_open (client_name, options, &status, server_name);
+  }  
+  
+  if (mClient == NULL) {
+    //fprintf (stderr, "jack_client_open() failed, "
+    //      "status = 0x%2.0x\n", status);
+    if (status & JackServerFailed) {
+      fprintf (stderr, "Unable to connect to JACK server\n");
+      //std::cerr << "ERROR: Maybe the JACK server is not running?" << std::endl;
+      //std::cerr << gPrintSeparator << std::endl;
+    }
+    //std::exit(1);
+    throw std::runtime_error("Maybe the JACK server is not running?");
+  }
+  if (status & JackServerStarted) {
+    fprintf (stderr, "JACK server started\n");
+  }
+  if (status & JackNameNotUnique) {
+    client_name = jack_get_client_name(mClient);
+    fprintf (stderr, "unique name `%s' assigned\n", client_name);
+  }
+
+  // Set function to call if Jack shuts down
+  jack_on_shutdown (mClient, this->jackShutdown, 0);
+
+  // Create input and output channels
+  createChannels();
+
+  // Allocate buffer memory to read and write
+  mSizeInBytesPerChannel = getSizeInBytesPerChannel();
+  int size_input  = mSizeInBytesPerChannel * getNumInputChannels();
+  int size_output = mSizeInBytesPerChannel * getNumOutputChannels();
+  mInputPacket = new int8_t[size_input];
+  mOutputPacket = new int8_t[size_output];
+
+  // Buffer size member
+  mNumFrames = getBufferSizeInSamples(); 
+
+  // Initialize Buffer array to read and write audio
+  mInBuffer.resize(mNumInChans);
+  mOutBuffer.resize(mNumOutChans);
+
+  // Initialize and asign memory for ProcessPlugins Buffers
+  mInProcessBuffer.resize(mNumInChans);
+  mOutProcessBuffer.resize(mNumOutChans);
+
+  int nframes = getBufferSizeInSamples();
+  for (int i = 0; i < mNumInChans; i++) {
+    mInProcessBuffer[i] = new sample_t[nframes];
+    // set memory to 0
+    std::memset(mInProcessBuffer[i], 0, sizeof(sample_t) * nframes);
+  }
+  for (int i = 0; i < mNumOutChans; i++) {
+    mOutProcessBuffer[i] = new sample_t[nframes];
+    // set memory to 0
+    std::memset(mOutProcessBuffer[i], 0, sizeof(sample_t) * nframes);
+  }
+}
+
+
+//*******************************************************************************
+void JackAudioInterface::createChannels()
+{
+  //Create Input Ports
+  mInPorts.resize(mNumInChans);
+  for (int i = 0; i < mNumInChans; i++)
+    {
+      QString inName;
+      QTextStream (&inName) << "send_" << i+1;
+      mInPorts[i] = jack_port_register (mClient, inName.toLatin1(),
+                                       JACK_DEFAULT_AUDIO_TYPE,
+                                       JackPortIsInput, 0);
+    }
+
+  //Create Output Ports
+  mOutPorts.resize(mNumOutChans);
+  for (int i = 0; i < mNumInChans; i++)
+    {
+      QString outName;
+      QTextStream (&outName) << "receive_" << i+1;
+      mOutPorts[i] = jack_port_register (mClient, outName.toLatin1(),
+                                       JACK_DEFAULT_AUDIO_TYPE,
+                                        JackPortIsOutput, 0);
+    }
+}
+
+
+//*******************************************************************************
+uint32_t JackAudioInterface::getSampleRate() const 
+{
+  return jack_get_sample_rate(mClient);
+}
+
+
+//*******************************************************************************
+JackAudioInterface::samplingRateT JackAudioInterface::getSampleRateType() const
+{
+  uint32_t rate = jack_get_sample_rate(mClient);
+
+  if      ( rate == 22050 ) {
+    return JackAudioInterface::SR22; }
+  else if ( rate == 32000 ) {
+    return JackAudioInterface::SR32; }
+  else if ( rate == 44100 ) {
+    return JackAudioInterface::SR44; }
+  else if ( rate == 48000 ) {
+    return JackAudioInterface::SR48; }
+  else if ( rate == 88200 ) {
+    return JackAudioInterface::SR88; }
+  else if ( rate == 96000 ) {
+    return JackAudioInterface::SR96; }
+  else if ( rate == 19200 ) {
+    return JackAudioInterface::SR192; }
+
+  return JackAudioInterface::UNDEF;
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::getSampleRateFromType(samplingRateT rate_type)
+{
+  int sample_rate = 0;
+  switch (rate_type)
+    {
+    case SR22 :
+      sample_rate = 22050;
+      return sample_rate;
+      break;
+    case SR32 :
+      sample_rate = 32000;
+      return sample_rate;
+      break;
+    case SR44 :
+      sample_rate = 44100;
+      return sample_rate;
+      break;
+    case SR48 :
+      sample_rate = 48000;
+      return sample_rate;
+      break;
+    case SR88 :
+      sample_rate = 88200;
+      return sample_rate;
+      break;
+    case SR96 :
+      sample_rate = 96000;
+      return sample_rate;
+      break;
+    case SR192 :
+      sample_rate = 192000;
+      return sample_rate;
+      break;
+    default:
+      return sample_rate;
+      break;
+    }
+
+  return sample_rate;
+}
+
+//*******************************************************************************
+uint32_t JackAudioInterface::getBufferSizeInSamples() const 
+{
+  return jack_get_buffer_size(mClient);
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::getAudioBitResolution() const
+{
+  return mAudioBitResolution;
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::getNumInputChannels() const
+{
+  return mNumInChans;
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::getNumOutputChannels() const
+{
+  return mNumOutChans;
+}
+
+
+//*******************************************************************************
+size_t JackAudioInterface::getSizeInBytesPerChannel() const
+{
+  return (getBufferSizeInSamples() * getAudioBitResolution()/8);
+}
+
+//*******************************************************************************
+void JackAudioInterface::setProcessCallback()
+{
+  std::cout << "Setting JACK Process Callback..." << std::endl;
+  if ( int code = 
+       jack_set_process_callback(mClient, JackAudioInterface::wrapperProcessCallback, this)
+       )
+    {
+      //std::cerr << "Could not set the process callback" << std::endl;
+      //return(code);
+      (void) code; // to avoid compiler warnings
+      throw std::runtime_error("Could not set the Jack process callback");
+      //std::exit(1);
+    }
+  std::cout << "SUCCESS" << std::endl;
+  std::cout << gPrintSeparator << std::endl;
+  //return(0);
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::startProcess() const
+{
+  //Tell the JACK server that we are ready to roll.  Our
+  //process() callback will start running now.
+  if ( int code = (jack_activate(mClient)) ) 
+    {
+      std::cerr << "Cannot activate client" << std::endl;
+    return(code);
+    }
+  return(0);
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::stopProcess() const
+{
+  QMutexLocker locker(&sJackMutex);
+  if ( int code = (jack_client_close(mClient)) )
+    {
+      std::cerr << "Cannot disconnect client" << std::endl;
+      return(code);
+    }
+  return(0);
+}
+
+
+//*******************************************************************************
+void JackAudioInterface::jackShutdown (void*)
+{
+  //std::cout << "The Jack Server was shut down!" << std::endl;
+  throw std::runtime_error("The Jack Server was shut down!");
+  //std::cout << "Exiting program..." << std::endl;
+  //std::exit(1);
+}
+
+
+//*******************************************************************************
+/*
+void JackAudioInterface::setRingBuffers
+(const std::tr1::shared_ptr<RingBuffer> InRingBuffer,
+ const std::tr1::shared_ptr<RingBuffer> OutRingBuffer)
+{
+  mInRingBuffer = InRingBuffer;
+  mOutRingBuffer = OutRingBuffer;
+}
+*/
+
+
+//*******************************************************************************
+// Before sending and reading to Jack, we have to round to the sample resolution
+// that the program is using. Jack uses 32 bits (gJackBitResolution in globals.h)
+// by default
+void JackAudioInterface::computeNetworkProcessFromNetwork()
+{
+  /// \todo cast *mInBuffer[i] to the bit resolution
+  //cout << mNumFrames << endl;
+  // Output Process (from NETWORK to JACK)
+  // ----------------------------------------------------------------
+  // Read Audio buffer from RingBuffer (read from incoming packets)
+  //mOutRingBuffer->readSlotNonBlocking( mOutputPacket );
+  mJackTrip->receiveNetworkPacket( mOutputPacket );
+
+  // Extract separate channels to send to Jack
+  for (int i = 0; i < mNumOutChans; i++) {
+    //--------
+    // This should be faster for 32 bits
+    //std::memcpy(mOutBuffer[i], &mOutputPacket[i*mSizeInBytesPerChannel],
+    //         mSizeInBytesPerChannel);
+    //--------
+    sample_t* tmp_sample = mOutBuffer[i]; //sample buffer for channel i
+    for (int j = 0; j < mNumFrames; j++) {
+      //std::memcpy(&tmp_sample[j], &mOutputPacket[(i*mSizeInBytesPerChannel) + (j*4)], 4);
+      // Change the bit resolution on each sample
+      //cout << tmp_sample[j] << endl;
+      fromBitToSampleConversion(&mOutputPacket[(i*mSizeInBytesPerChannel) 
+                                              + (j*mBitResolutionMode)],
+                               &tmp_sample[j],
+                               mBitResolutionMode);
+    }
+  }
+}
+
+
+//*******************************************************************************
+void JackAudioInterface::computeNetworkProcessToNetwork()
+{
+  // Input Process (from JACK to NETWORK)
+  // ----------------------------------------------------------------
+  // Concatenate  all the channels from jack to form packet
+  for (int i = 0; i < mNumInChans; i++) {  
+    //--------
+    // This should be faster for 32 bits
+    //std::memcpy(&mInputPacket[i*mSizeInBytesPerChannel], mInBuffer[i],
+    //         mSizeInBytesPerChannel);
+    //--------
+    sample_t* tmp_sample = mInBuffer[i]; //sample buffer for channel i
+    sample_t* tmp_process_sample = mOutProcessBuffer[i]; //sample buffer from the output process
+    sample_t tmp_result;
+    for (int j = 0; j < mNumFrames; j++) {
+      //std::memcpy(&tmp_sample[j], &mOutputPacket[(i*mSizeInBytesPerChannel) + (j*4)], 4);
+      // Change the bit resolution on each sample
+
+      // Add the input jack buffer to the buffer resulting from the output process
+      tmp_result = tmp_sample[j] + tmp_process_sample[j];
+      fromSampleToBitConversion(&tmp_result,
+                               &mInputPacket[(i*mSizeInBytesPerChannel)
+                                             + (j*mBitResolutionMode)],
+                               mBitResolutionMode);
+    }
+  }
+  // Send Audio buffer to RingBuffer (these goes out as outgoing packets)
+  //mInRingBuffer->insertSlotNonBlocking( mInputPacket );
+  mJackTrip->sendNetworkPacket( mInputPacket );
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::processCallback(jack_nframes_t nframes)
+{
+  // Get input and output buffers from JACK
+  //-------------------------------------------------------------------
+  for (int i = 0; i < mNumInChans; i++) {
+    // Input Ports are READ ONLY
+    mInBuffer[i] = (sample_t*) jack_port_get_buffer(mInPorts[i], nframes);
+  }
+  for (int i = 0; i < mNumOutChans; i++) {
+    // Output Ports are WRITABLE
+    mOutBuffer[i] = (sample_t*) jack_port_get_buffer(mOutPorts[i], nframes);
+  }
+  //-------------------------------------------------------------------
+  // TEST: Loopback
+  // To test, uncomment and send audio to client input. The same audio
+  // should come out as output in the first channel
+  //memcpy (mOutBuffer[0], mInBuffer[0], sizeof(sample_t) * nframes);
+  //memcpy (mOutBuffer[1], mInBuffer[1], sizeof(sample_t) * nframes);
+  //-------------------------------------------------------------------
+
+  // Allocate the Process Callback
+  //-------------------------------------------------------------------
+  // 1) First, process incoming packets
+  // ----------------------------------
+  computeNetworkProcessFromNetwork();
+
+
+  // 2) Dynamically allocate ProcessPlugin processes
+  // -----------------------------------------------
+  // The processing will be done in order of allocation
+
+  ///\todo Implement for more than one process plugin, now it just works propertely with one.
+  /// do it chaining outputs to inputs in the buffers. May need a tempo buffer
+  for (int i = 0; i < mNumInChans; i++) {
+    std::memset(mInProcessBuffer[i], 0, sizeof(sample_t) * nframes);
+    std::memcpy(mInProcessBuffer[i], mOutBuffer[i], sizeof(sample_t) * nframes);
+  }
+  for (int i = 0; i < mNumOutChans; i++) {
+    std::memset(mOutProcessBuffer[i], 0, sizeof(sample_t) * nframes);
+  }
+
+  for (int i = 0; i < mProcessPlugins.size(); i++) {
+    //mProcessPlugins[i]->compute(nframes, mOutBuffer.data(), mInBuffer.data());
+    mProcessPlugins[i]->compute(nframes, mInProcessBuffer.data(), mOutProcessBuffer.data());
+  }
+
+
+  // 3) Finally, send packets to peer
+  // --------------------------------
+  computeNetworkProcessToNetwork();
+
+  
+  ///************PROTORYPE FOR CELT**************************
+  ///********************************************************
+  /*
+  CELTMode* mode;
+  int* error;
+  mode = celt_mode_create(48000, 2, 64, error);
+  */
+  //celt_mode_create(48000, 2, 64, NULL);
+  //unsigned char* compressed;
+  //CELTEncoder* celtEncoder;
+  //celt_encode_float(celtEncoder, mInBuffer, NULL, compressed, );
+  
+  ///********************************************************
+  ///********************************************************
+
+
+
+  return 0;
+}
+
+
+//*******************************************************************************
+int JackAudioInterface::wrapperProcessCallback(jack_nframes_t nframes, void *arg) 
+{
+  return static_cast<JackAudioInterface*>(arg)->processCallback(nframes);
+}
+
+
+//*******************************************************************************
+// This function quantize from 32 bit to a lower bit resolution
+// 24 bit is not working yet
+void JackAudioInterface::fromSampleToBitConversion(const sample_t* const input,
+                                                  int8_t* output,
+                                                  const audioBitResolutionT targetBitResolution)
+{
+  int8_t tmp_8;
+  uint8_t tmp_u8; // unsigned to quantize the remainder in 24bits
+  int16_t tmp_16;
+  sample_t tmp_sample;
+  sample_t tmp_sample16;
+  sample_t tmp_sample8;
+  switch (targetBitResolution)
+    {
+    case BIT8 : 
+      // 8bit integer between -128 to 127
+      tmp_sample = floor( (*input) * 128.0 ); // 2^7 = 128.0
+      tmp_8 = static_cast<int8_t>(tmp_sample);
+      std::memcpy(output, &tmp_8, 1); // 8bits = 1 bytes
+      break;
+    case BIT16 :
+      // 16bit integer between -32768 to 32767
+      tmp_sample = floor( (*input) * 32768.0 ); // 2^15 = 32768.0
+      tmp_16 = static_cast<int16_t>(tmp_sample);
+      std::memcpy(output, &tmp_16, 2); // 16bits = 2 bytes
+      break;
+    case BIT24 :
+      // To convert to 24 bits, we first quantize the number to 16bit
+      tmp_sample = (*input) * 32768.0; // 2^15 = 32768.0
+      tmp_sample16 = floor(tmp_sample);
+      tmp_16 = static_cast<int16_t>(tmp_sample16);
+
+      // Then we compute the remainder error, and quantize that part into an 8bit number
+      // Note that this remainder is always positive, so we use an unsigned integer
+      tmp_sample8 = floor ((tmp_sample - tmp_sample16)  //this is a positive number, between 0.0-1.0
+                          * 256.0);
+      tmp_u8 = static_cast<uint8_t>(tmp_sample8);
+
+      // Finally, we copy the 16bit number in the first 2 bytes,
+      // and the 8bit number in the third bite
+      std::memcpy(output, &tmp_16, 2); // 16bits = 2 bytes
+      std::memcpy(output+2, &tmp_u8, 1); // 8bits = 1 bytes
+      break;
+    case BIT32 :
+      std::memcpy(output, input, 4); // 32bit = 4 bytes
+      break;
+    }
+}
+
+
+//*******************************************************************************
+void JackAudioInterface::fromBitToSampleConversion(const int8_t* const input,
+                                                  sample_t* output,
+                                                  const audioBitResolutionT sourceBitResolution)
+{
+  int8_t tmp_8;
+  uint8_t tmp_u8;
+  int16_t tmp_16;
+  sample_t tmp_sample;
+  sample_t tmp_sample16;
+  sample_t tmp_sample8;
+  switch (sourceBitResolution)
+    {
+    case BIT8 : 
+      tmp_8 = *input;
+      tmp_sample = static_cast<sample_t>(tmp_8) / 128.0;
+      std::memcpy(output, &tmp_sample, 4); // 4 bytes
+      break;
+    case BIT16 :
+      tmp_16 = *( reinterpret_cast<const int16_t*>(input) ); // *((int16_t*) input);
+      tmp_sample = static_cast<sample_t>(tmp_16) / 32768.0;
+      std::memcpy(output, &tmp_sample, 4); // 4 bytes
+      break;
+    case BIT24 :
+      // We first extract the 16bit and 8bit number from the 3 bytes
+      tmp_16 = *( reinterpret_cast<const int16_t*>(input) );
+      tmp_u8 = *( reinterpret_cast<const uint8_t*>(input+2) );
+
+      // Then we recover the number
+      tmp_sample16 = static_cast<sample_t>(tmp_16);
+      tmp_sample8 = static_cast<sample_t>(tmp_u8) / 256.0;
+      tmp_sample =  (tmp_sample16 +  tmp_sample8) / 32768.0;
+      std::memcpy(output, &tmp_sample, 4); // 4 bytes
+      break;
+    case BIT32 :
+      std::memcpy(output, input, 4); // 4 bytes
+      break;
+    }
+}
+
+
+//*******************************************************************************
+//void JackAudioInterface::appendProcessPlugin(const std::tr1::shared_ptr<ProcessPlugin> plugin)
+void JackAudioInterface::appendProcessPlugin(ProcessPlugin* plugin)
+{
+  /// \todo check that channels in ProcessPlugins are less or same that jack channels
+  if ( plugin->getNumInputs() ) {}
+  mProcessPlugins.append(plugin);
+}
+
+
+
+//*******************************************************************************
+void JackAudioInterface::connectDefaultPorts()
+{
+  const char** ports;
+
+  // Get physical output (capture) ports
+  if ( (ports =
+       jack_get_ports (mClient, NULL, NULL,
+                      JackPortIsPhysical | JackPortIsOutput)) == NULL)
+    {
+      cout << "WARING: Cannot find any physical capture ports" << endl;
+    }
+  else
+    {
+      // Connect capure ports to jacktrip send
+      for (int i = 0; i < mNumInChans; i++) 
+       {
+         // Check that we don't run out of capture ports
+         if ( ports[i] != NULL ) {
+           jack_connect(mClient, ports[i], jack_port_name(mInPorts[i]));
+         }
+       }
+      std::free(ports);
+    }
+  
+  // Get physical input (playback) ports
+  if ( (ports =
+       jack_get_ports (mClient, NULL, NULL,
+                      JackPortIsPhysical | JackPortIsInput)) == NULL)
+    {
+      cout << "WARING: Cannot find any physical playback ports" << endl;
+    }
+  else 
+    {
+      // Connect playback ports to jacktrip receive
+      for (int i = 0; i < mNumOutChans; i++) 
+       {
+         // Check that we don't run out of capture ports
+         if ( ports[i] != NULL ) {
+           jack_connect(mClient, jack_port_name(mOutPorts[i]), ports[i]);
+         }
+       }
+      std::free(ports);
+    }
+}
diff --git a/src/JackAudioInterface.h b/src/JackAudioInterface.h
new file mode 100644 (file)
index 0000000..2b01ff2
--- /dev/null
@@ -0,0 +1,305 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackAudioInterface.h
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+
+#ifndef __JACKAUDIOINTERFACE_H__
+#define __JACKAUDIOINTERFACE_H__
+
+#include <iostream>
+#include <tr1/memory> //for shared_ptr
+#include <functional> //for mem_fun_ref
+#include <jack/jack.h>
+
+#include <QVector>
+#include <QVarLengthArray>
+#include <QMutex>
+
+
+#include "jacktrip_types.h"
+#include "ProcessPlugin.h"
+
+class JackTrip; //forward declaration
+
+
+/** \brief Class that provides an interface with the Jack Audio Server
+ *
+ * \todo implement srate_callback
+ * \todo automatically starts jack with buffer and sample rate settings specified by the user
+ */
+class JackAudioInterface
+{
+public:
+
+  /// \brief Enum for Audio Resolution in bits
+  /// \todo implement this into the class, now it's using jack default of 32 bits
+  enum audioBitResolutionT {
+    BIT8  = 1, ///< 8 bits
+    BIT16 = 2, ///< 16 bits (default)
+    BIT24 = 3, ///< 24 bits
+    BIT32 = 4  ///< 32 bits
+  };
+  
+  /// \brief Sampling Rates supported by JACK
+  enum samplingRateT {
+    SR22, ///<  22050 Hz
+    SR32, ///<  32000 Hz
+    SR44, ///<  44100 Hz
+    SR48, ///<  48000 Hz
+    SR88, ///<  88200 Hz
+    SR96, ///<  96000 Hz
+    SR192, ///< 192000 Hz
+    UNDEF ///< Undefined
+  };
+
+  /** \brief The class constructor
+   * \param jacktrip Pointer to the JackTrip class that connects all classes (mediator)
+   * \param NumInChans Number of Input Channels
+   * \param NumOutChans Number of Output Channels
+   * \param AudioBitResolution Audio Sample Resolutions in bits
+   * \param ClientName Client name in Jack
+   */
+  JackAudioInterface(JackTrip* jacktrip,
+                    int NumInChans, int NumOutChans,
+         audioBitResolutionT AudioBitResolution = BIT16,
+         const char* ClientName = "JackTrip");
+
+  /** \brief The class destructor
+   */
+  virtual ~JackAudioInterface();
+
+  /** \brief Setup the client
+   */
+  void setup();
+
+  /** \brief Get the Jack Server Sampling Rate, in samples/second
+   */
+  uint32_t getSampleRate() const;
+
+  /** \brief Get the Jack Server Sampling Rate Enum Type samplingRateT
+   * \return  JackAudioInterface::samplingRateT enum type
+   */
+  samplingRateT getSampleRateType() const;
+
+  /** \brief Helper function to get the sample rate (in Hz) for a
+   * JackAudioInterface::samplingRateT
+   * \param rate_type  JackAudioInterface::samplingRateT enum type
+   * \return Sample Rate in Hz
+   */
+  static int getSampleRateFromType(samplingRateT rate_type);
+
+  /** \brief Get the Jack Server Buffer Size, in samples
+   */
+  uint32_t getBufferSizeInSamples() const;
+
+  /** \brief Get the Jack Server Buffer Size, in bytes
+   */
+  uint32_t getBufferSizeInBytes() const 
+  { 
+    return (getBufferSizeInSamples() * getAudioBitResolution()/8);
+  }
+  
+  /** \brief Get the Audio Bit Resolution, in bits
+   *
+   * This is one of the audioBitResolutionT set in construction
+   */
+  int getAudioBitResolution() const;
+
+  /// \brief Get Number of Input Channels
+  int getNumInputChannels() const;
+
+  /// \brief Get Number of Output Channels
+  int getNumOutputChannels() const;
+
+  /// \brief Get size of each audio per channel, in bytes
+  size_t getSizeInBytesPerChannel() const;
+
+  /** \brief Tell the JACK server that we are ready to roll. The
+   * process-callback will start running. This runs on its own thread.
+   * \return 0 on success, otherwise a non-zero error code
+   */
+  int startProcess() const;
+
+  /** \brief Stops the process-callback thread
+   * \return 0 on success, otherwise a non-zero error code
+   */
+  int stopProcess() const;
+
+  /** \brief Set the pointer to the Input and Output RingBuffer
+   * that'll be use to read and write audio
+   *
+   * These RingBuffer<EM>s</EM> are used to read and write audio samples on 
+   * each JACK callback.
+   * \todo If the RingBuffer is blocked, the callback should stay
+   * on the last buffer, as in JackTrip (wavetable synth) 
+   * \param InRingBuffer RingBuffer to read samples <B>from</B>
+   * \param OutRingBuffer RingBuffer to write samples <B>to</B>
+   */
+  /*
+  void setRingBuffers(const std::tr1::shared_ptr<RingBuffer> InRingBuffer,
+                     const std::tr1::shared_ptr<RingBuffer> OutRingBuffer);
+  */
+
+  /** \brief Append a ProcessPlugin. The order of processing is determined by
+   * the order by which appending is done.
+   * \param plugin a ProcesPlugin smart pointer. Create the object instance
+   * using something like:\n
+   * <tt>std::tr1::shared_ptr<ProcessPluginName> loopback(new ProcessPluginName);</tt>
+   */
+  //void appendProcessPlugin(const std::tr1::shared_ptr<ProcessPlugin> plugin);
+  void appendProcessPlugin(ProcessPlugin* plugin);
+
+  /** \brief Convert a 32bit number (sample_t) into one of the bit resolution
+   * supported (audioBitResolutionT).
+   *
+   * The result is stored in an int_8 array of the
+   * appropriate size to hold the value. The caller is responsible to allocate 
+   * enough space to store the result.
+   */
+  static void fromSampleToBitConversion(const sample_t* const input,
+                                       int8_t* output,
+                                       const audioBitResolutionT targetBitResolution);
+
+  /** \brief Convert a audioBitResolutionT bit resolution number into a 
+   * 32bit number (sample_t)
+   *
+   * The result is stored in an sample_t array of the
+   * appropriate size to hold the value. The caller is responsible to allocate 
+   * enough space to store the result.
+   */
+  static void fromBitToSampleConversion(const int8_t* const input,
+                                       sample_t* output,
+                                       const audioBitResolutionT sourceBitResolution);
+
+  /// \brief Connect the default ports, capture to sends, and receives to playback
+  void connectDefaultPorts();
+
+  /// \brief Set Client Name to something different that the default (JackTrip)
+  void setClientName(const char* ClientName)
+  { mClientName = ClientName; }
+
+private:
+
+  /** \brief Private method to setup a client of the Jack server.
+   * \exception std::runtime_error Can't start Jack
+   *
+   * This method is called by the class constructors. It does the following:\n
+   *  - Connects to the JACK server
+   *  - Sets the shutdown process callback
+   *  - Creates the appropriate number of input and output channels
+   */
+  void setupClient();
+
+  /** \brief Creates input and output channels in the Jack client
+   */
+  void createChannels();
+  /** \brief JACK calls this shutdown_callback if the server ever shuts down or
+   * decides to disconnect the client.
+   */
+  static void jackShutdown(void*);
+  
+  /// \brief Sets the part of the process callback that sends and receive packets
+  //void computeNetworkProcess();
+
+  /// \brief Compute the process to receive packets to JACK
+  void computeNetworkProcessFromNetwork();
+
+  /// \brief Compute the process from JACK to send packets
+  void computeNetworkProcessToNetwork();
+
+  /** \brief Set the process callback of the member function processCallback.
+   * This process will be called by the JACK server whenever there is work to be done.
+   */
+  void setProcessCallback();
+
+  /** \brief JACK process callback
+   * 
+   * This is the function to be called to process audio. This function is 
+   * of the type JackProcessCallback, which is defined as:\n
+   * <tt>typedef int(* JackProcessCallback)(jack_nframes_t nframes, void *arg)</tt>
+   * \n
+   * See
+   * http://jackaudio.org/files/docs/html/types_8h.html#4923142208a8e7dacf00ca7a10681d2b
+   * for more details
+   */
+  int processCallback(jack_nframes_t nframes);
+  
+  /** \brief Wrapper to cast the member processCallback to a static function pointer
+   * that can be used with <tt>jack_set_process_callback</tt>
+   *
+   * <tt>jack_set_process_callback</tt> needs a static member function pointer. A normal
+   * member function won't work because a <b><i>this</i></b> pointer is passed under the scenes.
+   * That's why we 
+   * need to cast the member funcion processCallback to the static function
+   * wrapperProcessCallback. The callback is then set as:\n
+   * <tt>jack_set_process_callback(mClient, JackAudioInterface::wrapperProcessCallback,
+   *                              this)</tt>
+   */
+  // reference : http://article.gmane.org/gmane.comp.audio.jackit/12873
+  static int wrapperProcessCallback(jack_nframes_t nframes, void *arg) ;
+
+
+  int mNumInChans;///< Number of Input Channels
+  int mNumOutChans; ///<  Number of Output Channels
+  int mNumFrames; ///< Buffer block size, in samples
+  int mAudioBitResolution; ///< Bit resolution in audio samples
+  audioBitResolutionT mBitResolutionMode; ///< Bit resolution (audioBitResolutionT) mode
+
+  jack_client_t* mClient; ///< Jack Client
+  const char* mClientName; ///< Jack Client Name
+  QVarLengthArray<jack_port_t*> mInPorts; ///< Vector of Input Ports (Channels)
+  QVarLengthArray<jack_port_t*> mOutPorts; ///< Vector of Output Ports (Channels)
+  //jack_port_t** mInPorts; ///< Vector of Input Ports (Channels)
+  //jack_port_t** mOutPorts; ///< Vector of Output Ports (Channels)
+  QVarLengthArray<sample_t*> mInBuffer; ///< Vector of Input buffers/channel read from JACK
+  QVarLengthArray<sample_t*> mOutBuffer; ///< Vector of Output buffer/channel to write to JACK
+
+  QVarLengthArray<sample_t*> mInProcessBuffer;///< Vector of Input buffers/channel for ProcessPlugin
+  QVarLengthArray<sample_t*> mOutProcessBuffer;///< Vector of Output buffers/channel for ProcessPlugin
+
+  int8_t* mInputPacket; ///< Packet containing all the channels to read from the RingBuffer
+  int8_t* mOutputPacket;  ///< Packet containing all the channels to send to the RingBuffer
+  size_t mSizeInBytesPerChannel; ///< Size in bytes per audio channel
+
+  QVector<ProcessPlugin*> mProcessPlugins; ///< Vector of ProcesPlugin<EM>s</EM>
+  JackTrip* mJackTrip; ///< JackTrip mediator class
+
+  static QMutex sJackMutex; ///< Mutex to make thread safe jack functions that are not
+};
+
+
+#endif
diff --git a/src/JackTrip.cpp b/src/JackTrip.cpp
new file mode 100644 (file)
index 0000000..6384504
--- /dev/null
@@ -0,0 +1,466 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTrip.cpp
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+#include "JackTrip.h"
+#include "UdpDataProtocol.h"
+#include "RingBufferWavetable.h"
+#include "jacktrip_globals.h"
+
+#include <iostream>
+//#include <unistd.h> // for usleep, sleep
+#include <cstdlib>
+#include <stdexcept>
+
+#include <QHostAddress>
+#include <QThread>
+
+using std::cout; using std::endl;
+
+
+
+//*******************************************************************************
+JackTrip::JackTrip(jacktripModeT JacktripMode,
+                  dataProtocolT DataProtocolType,
+       int NumChans,
+       int BufferQueueLength,
+       unsigned int redundancy,
+       JackAudioInterface::audioBitResolutionT AudioBitResolution,
+       DataProtocol::packetHeaderTypeT PacketHeaderType,
+       underrunModeT UnderRunMode,
+       int receiver_bind_port, int sender_bind_port,
+       int receiver_peer_port, int sender_peer_port) :
+  mJackTripMode(JacktripMode),
+  mDataProtocol(DataProtocolType),
+  mPacketHeaderType(PacketHeaderType),
+  mNumChans(NumChans),
+  mBufferQueueLength(BufferQueueLength),
+  mSampleRate(0),
+  mAudioBufferSize(0),
+  mAudioBitResolution(AudioBitResolution),
+  mDataProtocolSender(NULL),
+  mDataProtocolReceiver(NULL),
+  mJackAudio(NULL),
+  mPacketHeader(NULL),
+  mUnderRunMode(UnderRunMode),
+  mSendRingBuffer(NULL),
+  mReceiveRingBuffer(NULL),
+  mReceiverBindPort(receiver_bind_port),
+  mSenderPeerPort(sender_peer_port),
+  mSenderBindPort(sender_bind_port),
+  mReceiverPeerPort(receiver_peer_port),
+  mRedundancy(redundancy),
+  mJackClientName("JackTrip")
+{}
+
+
+//*******************************************************************************
+JackTrip::~JackTrip()
+{
+  delete mDataProtocolSender;
+  delete mDataProtocolReceiver;
+  delete mJackAudio;
+  delete mPacketHeader;
+  delete mSendRingBuffer;
+  delete mReceiveRingBuffer;
+}
+
+
+//*******************************************************************************
+void JackTrip::setupJackAudio()
+{
+  // Create JackAudioInterface Client Object
+  mJackAudio = new JackAudioInterface(this, mNumChans, mNumChans, mAudioBitResolution);
+  mJackAudio->setClientName(mJackClientName);
+  mJackAudio->setup();
+  mSampleRate = mJackAudio->getSampleRate();
+  std::cout << "The Sampling Rate is: " << mSampleRate << std::endl;
+  std::cout << gPrintSeparator << std::endl;
+  mAudioBufferSize = mJackAudio->getBufferSizeInSamples();
+  int AudioBufferSizeInBytes = mAudioBufferSize*sizeof(sample_t);
+  std::cout << "The Audio Buffer Size is: " << mAudioBufferSize << " samples" << std::endl;
+  std::cout << "                      or: " << AudioBufferSizeInBytes 
+           << " bytes" << std::endl;
+  std::cout << gPrintSeparator << std::endl;
+  cout << "The Number of Channels is: " << mJackAudio->getNumInputChannels() << endl;
+  std::cout << gPrintSeparator << std::endl;
+  QThread::usleep(100);
+}
+
+
+//*******************************************************************************
+void JackTrip::setupDataProtocol()
+{
+  // Create DataProtocol Objects
+  switch (mDataProtocol) {
+  case UDP:
+    std::cout << "Using UDP Protocol" << std::endl;
+    std::cout << gPrintSeparator << std::endl;
+    QThread::usleep(100);
+    mDataProtocolSender = new UdpDataProtocol(this, DataProtocol::SENDER,
+                                              //mSenderPeerPort, mSenderBindPort,
+                                              mSenderBindPort, mSenderPeerPort,
+                                              mRedundancy);
+    mDataProtocolReceiver =  new UdpDataProtocol(this, DataProtocol::RECEIVER,
+                                                 mReceiverBindPort, mReceiverPeerPort,
+                                                 mRedundancy);
+    break;
+  case TCP:
+    throw std::invalid_argument("TCP Protocol is not implemented");
+    break;
+  case SCTP:
+    throw std::invalid_argument("SCTP Protocol is not implemented");
+    break;
+  default: 
+    throw std::invalid_argument("Protocol not defined or unimplemented");
+    break;
+  }
+  
+  // Set Audio Packet Size
+  mDataProtocolSender->setAudioPacketSize
+    (mJackAudio->getSizeInBytesPerChannel() * mNumChans);
+  mDataProtocolReceiver->setAudioPacketSize
+    (mJackAudio->getSizeInBytesPerChannel() * mNumChans);
+}
+
+
+//*******************************************************************************
+void JackTrip::setupRingBuffers()
+{
+  // Create RingBuffers with the apprioprate size
+  /// \todo Make all this operations cleaner
+  switch (mUnderRunMode) {
+  case WAVETABLE:
+    mSendRingBuffer = new RingBufferWavetable(mJackAudio->getSizeInBytesPerChannel() * mNumChans,
+                                             gDefaultOutputQueueLength);
+    mReceiveRingBuffer = new RingBufferWavetable(mJackAudio->getSizeInBytesPerChannel() * mNumChans,
+                                                mBufferQueueLength);
+    
+    break;
+  case ZEROS:
+    mSendRingBuffer = new RingBuffer(mJackAudio->getSizeInBytesPerChannel() * mNumChans,
+                                    gDefaultOutputQueueLength);
+    mReceiveRingBuffer = new RingBuffer(mJackAudio->getSizeInBytesPerChannel() * mNumChans,
+                                       mBufferQueueLength);
+    break;
+  default:
+    throw std::invalid_argument("Underrun Mode undefined");
+    break;
+  }
+}
+
+
+//*******************************************************************************
+void JackTrip::setPeerAddress(const char* PeerHostOrIP)
+{
+  mPeerAddress = PeerHostOrIP;
+}
+
+
+//*******************************************************************************
+void JackTrip::appendProcessPlugin(ProcessPlugin* plugin)
+{
+  mProcessPlugins.append(plugin);
+  //mJackAudio->appendProcessPlugin(plugin);
+}
+
+
+//*******************************************************************************
+void JackTrip::start()
+{
+  // Check if ports are already binded by another process on this machine
+  checkIfPortIsBinded(mReceiverBindPort);
+  checkIfPortIsBinded(mSenderBindPort);
+
+  // Set all classes and parameters
+  setupJackAudio();
+  createHeader(mPacketHeaderType);
+  setupDataProtocol();
+  setupRingBuffers();
+
+  // Start the threads for the specific mode
+  switch ( mJackTripMode )
+    {
+    case CLIENT :
+      clientStart();
+      break;
+    case SERVER :
+      serverStart();
+      break;
+    case CLIENTTOPINGSERVER :
+      clientPingToServerStart();
+      break;
+    default: 
+      throw std::invalid_argument("Jacktrip Mode  undefined");
+      break;
+    }
+  
+  // Start Threads
+  mJackAudio->startProcess();
+  for (int i = 0; i < mProcessPlugins.size(); ++i) {
+    mJackAudio->appendProcessPlugin(mProcessPlugins[i]);
+  }
+  mJackAudio->connectDefaultPorts();
+  mDataProtocolSender->start();
+  mDataProtocolReceiver->start();
+}
+
+
+//*******************************************************************************
+void JackTrip::stop()
+{
+  // Stop The Sender
+  mDataProtocolSender->stop();
+  mDataProtocolSender->wait();
+
+  // Stop The Receiver
+  mDataProtocolReceiver->stop();
+  mDataProtocolReceiver->wait();
+
+  // Stop the jack process callback
+  mJackAudio->stopProcess();
+
+  cout << "JackTrip Processes STOPPED!" << endl;
+  cout << gPrintSeparator << endl;
+
+  // Emit the jack stopped signal
+  emit signalProcessesStopped();
+}
+
+//*******************************************************************************
+void JackTrip::wait()
+{
+  mDataProtocolSender->wait();
+  mDataProtocolReceiver->wait();
+}
+
+
+//*******************************************************************************
+void JackTrip::clientStart()
+{
+  // For the Client mode, the peer (or server) address has to be specified by the user
+  if ( mPeerAddress.isEmpty() ) {
+    throw std::invalid_argument("Peer Address has to be set if you run in CLIENT mode");
+  }
+  else {
+    // Set the peer address
+    mDataProtocolSender->setPeerAddress( mPeerAddress.toLatin1().data() );
+    mDataProtocolReceiver->setPeerAddress( mPeerAddress.toLatin1().data() );
+    cout << "Peer Address set to: " << mPeerAddress.toStdString() << std::endl;
+    cout << gPrintSeparator << endl;
+  }
+}
+
+
+//*******************************************************************************
+void JackTrip::serverStart()
+{
+  // Set the peer address
+  if ( !mPeerAddress.isEmpty() ) {
+    std::cout << "WARNING: SERVER mode: Peer Address was set but will be deleted." << endl;
+    mPeerAddress.clear();
+  }
+
+  // Get the client address when it connects
+  cout << "Waiting for Connection From Client..." << endl;
+  QHostAddress peerHostAddress;
+  uint16_t peer_port;
+  QUdpSocket UdpSockTemp;// Create socket to wait for client
+
+  // Bind the socket
+  if ( !UdpSockTemp.bind(QHostAddress::Any, mReceiverBindPort,
+                         QUdpSocket::DefaultForPlatform) )
+  {
+    throw std::runtime_error("Could not bind UDP socket. It may be already binded.");
+  }
+  // Listen to client
+  while ( !UdpSockTemp.hasPendingDatagrams() ) { QThread::usleep(100000); }
+  char buf[1];
+  // set client address
+  UdpSockTemp.readDatagram(buf, 1, &peerHostAddress, &peer_port);
+  UdpSockTemp.close(); // close the socket
+
+  mPeerAddress = peerHostAddress.toString();
+  cout << "Client Connection Received from IP : " 
+       << qPrintable(mPeerAddress) << endl;
+  cout << gPrintSeparator << endl;
+
+  // Set the peer address to send packets (in the protocol sender)
+  mDataProtocolSender->setPeerAddress( mPeerAddress.toLatin1().constData() );
+  mDataProtocolReceiver->setPeerAddress( mPeerAddress.toLatin1().constData() );
+  // We reply to the same port the peer sent the packets
+  // This way we can go through NAT
+  // Because of the NAT traversal scheme, the portn need to be
+  // "symetric", e.g.:
+  // from Client to Server : src = 4474, dest = 4464
+  // from Server to Client : src = 4464, dest = 4474
+  mDataProtocolSender->setPeerPort(peer_port);
+  mDataProtocolReceiver->setPeerPort(peer_port);
+  setPeerPorts(peer_port);
+}
+
+//*******************************************************************************
+void JackTrip::clientPingToServerStart()
+{
+  // For the Client mode, the peer (or server) address has to be specified by the user
+  if ( mPeerAddress.isEmpty() ) {
+    throw std::invalid_argument("Peer Address has to be set if you run in CLIENTTOPINGSERVER mode");
+  }
+  else {
+    // Set the peer address
+    mDataProtocolSender->setPeerAddress( mPeerAddress.toLatin1().data() );
+  }
+
+  // Start Threads
+  mJackAudio->startProcess();
+  //mJackAudio->connectDefaultPorts();    
+  mDataProtocolSender->start();
+  //cout << "STARTED DATA PROTOCOL SENDER-----------------------------" << endl;
+  //mDataProtocolReceiver->start();
+
+  QHostAddress serverHostAddress;
+  QUdpSocket UdpSockTemp;// Create socket to wait for server answer
+  uint16_t server_port;
+
+  // Bind the socket
+  if ( !UdpSockTemp.bind(QHostAddress::Any,
+                        mReceiverBindPort,
+                        QUdpSocket::DefaultForPlatform) ) {
+    throw std::runtime_error("Could not bind UDP socket. It may be already binded.");
+  }
+  // Listen to server response
+  cout << "Waiting for server response..." << endl;
+  while ( !UdpSockTemp.hasPendingDatagrams() ) { QThread::usleep(100000); }
+  cout << "Received response from server!" << endl;
+  char buf[1];
+  // set client address
+  UdpSockTemp.readDatagram(buf, 1, &serverHostAddress, &server_port);
+  UdpSockTemp.close(); // close the socket
+
+  // Stop the sender thread to change server port
+  mDataProtocolSender->stop();
+  mDataProtocolSender->wait(); // Wait for the thread to terminate
+  /*
+  while ( mDataProtocolSender->isRunning() ) 
+    { 
+      cout << "IS RUNNING!" << endl;
+      QThread::usleep(100000);
+    }
+  */
+  cout << "Server port now set to: " << server_port-1 << endl;  
+  cout << gPrintSeparator << endl;
+  mDataProtocolSender->setPeerPort(server_port-1);
+  
+  // Start Threads
+  //mJackAudio->connectDefaultPorts();
+  mDataProtocolSender->start();
+  mDataProtocolReceiver->start();
+}
+
+
+//*******************************************************************************
+void JackTrip::createHeader(const DataProtocol::packetHeaderTypeT headertype)
+{
+  switch (headertype) {
+  case DataProtocol::DEFAULT :
+    mPacketHeader = new DefaultHeader(this);
+    break;
+  case DataProtocol::JAMLINK :
+    mPacketHeader = new JamLinkHeader(this);
+    break;
+  case DataProtocol::EMPTY :
+    mPacketHeader = new EmptyHeader(this);
+    break;
+  default :
+    throw std::invalid_argument("Undefined Header Type");
+    break;
+  }
+}
+
+
+//*******************************************************************************
+void JackTrip::putHeaderInPacket(int8_t* full_packet, int8_t* audio_packet)
+{
+  mPacketHeader->fillHeaderCommonFromAudio();
+  mPacketHeader->putHeaderInPacket(full_packet);
+  
+  int8_t* audio_part;
+  audio_part = full_packet + mPacketHeader->getHeaderSizeInBytes();
+  //std::memcpy(audio_part, audio_packet, mJackAudio->getBufferSizeInBytes());
+  std::memcpy(audio_part, audio_packet, mJackAudio->getSizeInBytesPerChannel() * mNumChans);
+}
+
+
+//*******************************************************************************
+int JackTrip::getPacketSizeInBytes() const
+{
+  //return (mJackAudio->getBufferSizeInBytes() + mPacketHeader->getHeaderSizeInBytes());
+  return (mJackAudio->getSizeInBytesPerChannel() * mNumChans  +
+         mPacketHeader->getHeaderSizeInBytes());
+}
+
+
+//*******************************************************************************
+void JackTrip::parseAudioPacket(int8_t* full_packet, int8_t* audio_packet)
+{
+  int8_t* audio_part;
+  audio_part = full_packet + mPacketHeader->getHeaderSizeInBytes();
+  //std::memcpy(audio_packet, audio_part, mJackAudio->getBufferSizeInBytes());
+  std::memcpy(audio_packet, audio_part, mJackAudio->getSizeInBytesPerChannel() * mNumChans);
+}
+
+
+//*******************************************************************************
+void JackTrip::checkPeerSettings(int8_t* full_packet)
+{
+  mPacketHeader->checkPeerSettings(full_packet);
+}
+
+
+//*******************************************************************************
+void JackTrip::checkIfPortIsBinded(int port)
+{
+  QUdpSocket UdpSockTemp;// Create socket to wait for client
+
+  // Bind the socket
+  if ( !UdpSockTemp.bind(QHostAddress::Any, port, QUdpSocket::DontShareAddress) )
+  {
+    UdpSockTemp.close(); // close the socket
+    throw std::runtime_error(
+        "Could not bind UDP socket. It may already be binded by another process on your machine. Try using a different port number");
+  }
+  UdpSockTemp.close(); // close the socket
+}
diff --git a/src/JackTrip.h b/src/JackTrip.h
new file mode 100644 (file)
index 0000000..69576f2
--- /dev/null
@@ -0,0 +1,313 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTrip.h
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+#ifndef __JACKTRIP_H__
+#define __JACKTRIP_H__
+
+#include <tr1/memory> //for shared_ptr
+
+#include <QObject>
+#include <QString>
+
+#include "DataProtocol.h"
+#include "JackAudioInterface.h"
+#include "PacketHeader.h"
+#include "RingBuffer.h"
+
+
+/** \brief Main class to creates a SERVER (to listen) or a CLIENT (to connect
+ * to a listening server) to send audio streams in the network.
+ *
+ * All audio and network settings can be set in this class.
+ * This class also acts as a Mediator between all the other class.
+ * Classes that uses JackTrip methods need to register with it.
+ */
+class JackTrip : public QThread
+{
+  Q_OBJECT;
+
+public:
+
+  //----------ENUMS------------------------------------------
+  /// \brief Enum for the data Protocol. At this time only UDP is implemented
+  enum dataProtocolT {
+    UDP, ///< Use UDP (User Datagram Protocol) 
+    TCP, ///< <B>NOT IMPLEMENTED</B>: Use TCP (Transmission Control Protocol)
+    SCTP ///< <B>NOT IMPLEMENTED</B>: Use SCTP (Stream Control Transmission Protocol)
+  };
+
+  /// \brief Enum for the JackTrip mode
+  enum jacktripModeT {
+    SERVER, ///< Run in Server Mode
+    CLIENT,  ///< Run in Client Mode
+    CLIENTTOPINGSERVER ///< Client of the Ping Server Mode
+  };
+
+  /// \brief Enum for the JackTrip Underrun Mode, when packets
+  enum underrunModeT {
+    WAVETABLE, ///< Loops on the last received packet
+    ZEROS  ///< Set new buffers to zero if there are no new ones
+  };
+  //---------------------------------------------------------
+
+
+  /** \brief The class Constructor with Default Parameters
+   * \param JacktripMode JackTrip::CLIENT or JackTrip::SERVER
+   * \param DataProtocolType JackTrip::dataProtocolT
+   * \param NumChans Number of Audio Channels (same for inputs and outputs)
+   * \param BufferQueueLength Audio Buffer for receiving packets
+   * \param AudioBitResolution Audio Sample Resolutions in bits
+   * \param redundancy redundancy factor for network data
+   */
+  JackTrip(jacktripModeT JacktripMode = CLIENT,
+          dataProtocolT DataProtocolType = UDP,
+          int NumChans = 2,
+          int BufferQueueLength = 8,
+          unsigned int redundancy = 1,
+          JackAudioInterface::audioBitResolutionT AudioBitResolution = 
+          JackAudioInterface::BIT16,
+          DataProtocol::packetHeaderTypeT PacketHeaderType = 
+          DataProtocol::DEFAULT,
+          underrunModeT UnderRunMode = WAVETABLE,
+     int receiver_bind_port = gDefaultPort,
+     int sender_bind_port = gDefaultPort,
+     int receiver_peer_port = gDefaultPort,
+     int sender_peer_port = gDefaultPort);
+  
+  /// \brief The class destructor
+  virtual ~JackTrip();
+
+  /// \brief Set the Peer Address for jacktripModeT::CLIENT mode only
+  void setPeerAddress(const char* PeerHostOrIP);
+
+  /** \brief Append a process plugin. Processes will be appended in order
+   * \param plugin Pointer to ProcessPlugin Class
+   */
+  //void appendProcessPlugin(const std::tr1::shared_ptr<ProcessPlugin> plugin);
+  void appendProcessPlugin(ProcessPlugin* plugin);
+
+  /// \brief Start the processing threads
+  void start();
+
+  /// \brief Stop the processing threads
+  void stop();
+
+  /// \brief Wait for all the threads to finish. This functions is used when JackTrip is 
+  /// run as a thread
+  void wait();
+
+  /// \brief Check if UDP port is already binded
+  /// \param port Port number
+  void checkIfPortIsBinded(int port);
+  
+  //------------------------------------------------------------------------------------
+  /// \name Methods to change parameters after construction
+  //@{
+  // 
+  /// \brief Sets (override) JackTrip Mode after construction
+  void setJackTripMode(jacktripModeT JacktripMode)
+  { mJackTripMode = JacktripMode; }
+  /// \brief Sets (override) DataProtocol Type after construction
+  void setDataProtocoType(dataProtocolT DataProtocolType)
+  { mDataProtocol = DataProtocolType; }
+  /// \brief Sets the Packet header type
+  void setPacketHeaderType(DataProtocol::packetHeaderTypeT PacketHeaderType)
+  { 
+    mPacketHeaderType = PacketHeaderType;
+    delete mPacketHeader;
+    mPacketHeader = NULL;
+    createHeader(mPacketHeaderType);
+  }
+  /// \brief Sets (override) Number of Channels after construction
+  /// \todo implement this, not working right now because channels cannot be changed after construction
+  //void setNumChannels(int NumChans)
+  //{ mNumChans=NumChans; }
+  /// \brief Sets (override) Buffer Queue Length Mode after construction
+  void setBufferQueueLength(int BufferQueueLength)
+  { mBufferQueueLength = BufferQueueLength; }
+  /// \brief Sets (override) Audio Bit Resolution after construction
+  void setAudioBitResolution(JackAudioInterface::audioBitResolutionT AudioBitResolution)
+  { mAudioBitResolution = AudioBitResolution; }
+  /// \brief Sets (override) Underrun Mode
+  void setUnderRunMode(underrunModeT UnderRunMode)
+  { mUnderRunMode = UnderRunMode; }
+  /// \brief Sets port numbers for the local and peer machine.
+  /// Receive port is <tt>port</tt>
+  void setAllPorts(int port)
+  {
+    mReceiverBindPort = port;
+    mSenderPeerPort = port;
+    mSenderBindPort = port;
+    mReceiverPeerPort = port;
+  }
+  /// \brief Sets port numbers to bind in RECEIVER and SENDER sockets.
+  void setBindPorts(int port)
+  {
+    mReceiverBindPort = port;
+    mSenderBindPort = port;
+  }
+  /// \brief Sets port numbers for the peer (remote) machine.
+  void setPeerPorts(int port)
+  {
+    mSenderPeerPort = port;
+    mReceiverPeerPort = port;
+  }
+  /// \brief Set Client Name to something different that the default (JackTrip)
+  void setClientName(char* ClientName)
+  { mJackClientName = ClientName; }
+  //@}
+  //------------------------------------------------------------------------------------
+
+
+  //------------------------------------------------------------------------------------
+  /// \name Mediator Functions
+  //@{
+  /// \todo Document all these functions
+  void createHeader(const DataProtocol::packetHeaderTypeT headertype);
+  void putHeaderInPacket(int8_t* full_packet, int8_t* audio_packet);
+  int getPacketSizeInBytes() const;
+  void parseAudioPacket(int8_t* full_packet, int8_t* audio_packet);
+  void sendNetworkPacket(const int8_t* ptrToSlot)
+  { mSendRingBuffer->insertSlotNonBlocking(ptrToSlot); }
+  void receiveNetworkPacket(int8_t* ptrToReadSlot)
+  { mReceiveRingBuffer->readSlotNonBlocking(ptrToReadSlot); }
+  void readAudioBuffer(int8_t* ptrToReadSlot)
+  { mSendRingBuffer->readSlotBlocking(ptrToReadSlot); }
+  void writeAudioBuffer(const int8_t* ptrToSlot)
+  { mReceiveRingBuffer->insertSlotNonBlocking(ptrToSlot); }
+  uint32_t getBufferSizeInSamples() const
+  { return mJackAudio->getBufferSizeInSamples(); }
+  JackAudioInterface::samplingRateT getSampleRateType() const
+  { return mJackAudio->getSampleRateType(); }
+  uint8_t getAudioBitResolution() const
+  { return mJackAudio->getAudioBitResolution(); }
+  int getNumInputChannels() const
+  { return mJackAudio->getNumInputChannels(); }
+  int getNumOutputChannels() const
+  {return mJackAudio->getNumOutputChannels(); }
+  void checkPeerSettings(int8_t* full_packet);
+  void increaseSequenceNumber()
+  { mPacketHeader->increaseSequenceNumber(); }
+  int getSequenceNumber() const
+  { return mPacketHeader->getSequenceNumber(); }
+  int getPeerSequenceNumber(int8_t* full_packet) const
+  { return mPacketHeader->getPeerSequenceNumber(full_packet); }
+  //@}
+  //------------------------------------------------------------------------------------
+
+
+public slots:
+  /// \brief Slot to stop all the processes and threads
+  void slotStopProcesses()
+  {
+    std::cout << "Stopping JackTrip..." << std::endl;
+    stop();
+  };
+
+  /** \brief This slot emits in turn the signal signalNoUdpPacketsForSeconds
+   * when UDP is waited for more than 30 seconds.
+   * 
+   * It is used to remove the thread from the server.
+   */
+  void slotUdpWatingTooLong(int wait_msec)
+  { 
+    int wait_time = 30000; // msec
+    if ( !(wait_msec%wait_time) ) {
+      std::cerr << "UDP WAITED MORE THAN 30 seconds." << std::endl;
+      emit signalNoUdpPacketsForSeconds();
+    }
+  }
+  
+
+signals:
+  /// \brieg Signal emitted when all the processes and threads are stopped
+  void signalProcessesStopped();
+  /// \brieg Signal emitted when no UDP Packets have been received for a while
+  void signalNoUdpPacketsForSeconds();
+
+
+private:
+
+  /// \brief Set the JackAudioInteface object
+  void setupJackAudio();
+  /// \brief Set the DataProtocol objects
+  void setupDataProtocol();
+  /// \brief Set the RingBuffer objects
+  void setupRingBuffers();
+  /// \brief Starts for the CLIENT mode
+  void clientStart();
+  /// \brief Starts for the SERVER mode
+  void serverStart();
+  /// \brief Stats for the Client to Ping Server
+  void clientPingToServerStart();
+
+  jacktripModeT mJackTripMode; ///< JackTrip::jacktripModeT
+  dataProtocolT mDataProtocol; ///< Data Protocol Tipe
+  DataProtocol::packetHeaderTypeT mPacketHeaderType; ///< Packet Header Type
+
+  int mNumChans; ///< Number of Channels (inputs = outputs)
+  int mBufferQueueLength; ///< Audio Buffer from network queue length
+  uint32_t mSampleRate; ///< Sample Rate
+  uint32_t mAudioBufferSize; ///< Audio buffer size to process on each callback
+  JackAudioInterface::audioBitResolutionT mAudioBitResolution; ///< Audio Bit Resolutions
+  QString mPeerAddress; ///< Peer Address to use in jacktripModeT::CLIENT Mode
+
+  /// Pointer to Abstract Type DataProtocol that sends packets
+  DataProtocol* mDataProtocolSender;
+  ///< Pointer to Abstract Type DataProtocol that receives packets
+  DataProtocol* mDataProtocolReceiver;
+  JackAudioInterface* mJackAudio; ///< Interface to Jack Client
+  PacketHeader* mPacketHeader; ///< Pointer to Packet Header
+  underrunModeT mUnderRunMode; ///< underrunModeT Mode
+
+  /// Pointer for the Send RingBuffer
+  RingBuffer* mSendRingBuffer;
+  /// Pointer for the Receive RingBuffer
+  RingBuffer* mReceiveRingBuffer;
+
+  int mReceiverBindPort; ///< Incoming (receiving) port for local machine
+  int mSenderPeerPort; ///< Incoming (receiving) port for peer machine
+  int mSenderBindPort; ///< Outgoing (sending) port for local machine
+  int mReceiverPeerPort; ///< Outgoing (sending) port for peer machine
+
+  unsigned int mRedundancy; ///< Redundancy factor in network data
+  const char* mJackClientName; ///< JackAudio Client Name
+
+  QVector<ProcessPlugin*> mProcessPlugins; ///< Vector of ProcesPlugin<EM>s</EM>
+};
+
+#endif
diff --git a/src/JackTripThread.cpp b/src/JackTripThread.cpp
new file mode 100644 (file)
index 0000000..5b3f52d
--- /dev/null
@@ -0,0 +1,102 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTripThread.cpp
+ * \author Juan-Pablo Caceres
+ * \date September 2008
+ */
+
+
+#include "JackTripThread.h"
+#include "NetKS.h"
+
+#include <iostream>
+#include <cstdlib>
+
+using std::cout; using std::endl;
+
+
+//*******************************************************************************
+void JackTripThread::run()
+{
+  JackTrip jacktrip(mJackTripMode);
+  jacktrip.setAllPorts(mPortNum);
+  
+  if ( mJackTripMode == JackTrip::CLIENT )
+    {
+      jacktrip.setPeerAddress(mPeerAddress);
+    }
+
+  NetKS netks;
+  jacktrip.appendProcessPlugin(&netks);
+  //netks.play();
+
+
+  //QThread::sleep(1);
+  jacktrip.start();
+  //netks.play();
+  jacktrip.wait();
+
+
+  cout << "******** AFTER JACKTRIPTHREAD START **************" << endl;
+  //QThread::sleep(9999999);
+
+
+
+  /*
+  jack_client_t* mClient;
+  const char* client_name = "JackThread";
+  const char* server_name = NULL;
+  jack_options_t options = JackNoStartServer;
+  jack_status_t status;
+
+  mClient = jack_client_open (client_name, options, &status, server_name);
+
+  if (mClient == NULL) {
+    fprintf (stderr, "jack_client_open() failed, "
+            "status = 0x%2.0x\n", status);
+    if (status & JackServerFailed) {
+      fprintf (stderr, "Unable to connect to JACK server\n");
+    }
+    std::exit(1);
+  }
+  if (status & JackServerStarted) {
+    fprintf (stderr, "JACK server started\n");
+  }
+  if (status & JackNameNotUnique) {
+    client_name = jack_get_client_name(mClient);
+    fprintf (stderr, "unique name `%s' assigned\n", client_name);
+  }
+  */
+
+
+}
diff --git a/src/JackTripThread.h b/src/JackTripThread.h
new file mode 100644 (file)
index 0000000..6825386
--- /dev/null
@@ -0,0 +1,64 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTripThread.h
+ * \author Juan-Pablo Caceres
+ * \date September 2008
+ */
+
+#ifndef __JACKTRIPTHREAD_H__
+#define __JACKTRIPTHREAD_H__
+
+#include <QThread>
+
+#include "JackTrip.h"
+
+/** \brief Test class that runs JackTrip inside a thread
+ */
+class JackTripThread : public QThread
+{
+public:
+  JackTripThread(JackTrip::jacktripModeT JacktripMode) : mJackTripMode(JacktripMode) {};
+  virtual ~JackTripThread(){};
+  void run();
+
+  void setPort(int port_num) { mPortNum = port_num; } ;
+  void setPeerAddress(const char* PeerHostOrIP) { mPeerAddress = PeerHostOrIP; }
+
+private:
+  JackTrip::jacktripModeT mJackTripMode; ///< JackTrip::jacktripModeT
+  int mPortNum;
+  const char* mPeerAddress; ///< Peer Address to use in jacktripModeT::CLIENT Mode
+};
+
+
+#endif //__JACKTRIPTHREAD_H__
diff --git a/src/JackTripWorker.cpp b/src/JackTripWorker.cpp
new file mode 100644 (file)
index 0000000..e20c4ba
--- /dev/null
@@ -0,0 +1,178 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTripWorker.cpp
+ * \author Juan-Pablo Caceres
+ * \date September 2008
+ */
+
+#include <iostream>
+#include <unistd.h>
+
+#include <QTimer>
+#include <QMutexLocker>
+
+#include "JackTripWorker.h"
+#include "JackTrip.h"
+#include "UdpMasterListener.h"
+#include "NetKS.h"
+#include "LoopBack.h"
+
+using std::cout; using std::endl;
+
+//*******************************************************************************
+JackTripWorker::JackTripWorker(UdpMasterListener* udpmasterlistener) :
+  mUdpMasterListener(NULL),
+  mSpawning(false),
+  mID(0),
+  mNumChans(1)
+{
+  /* From the QT Documentation:
+  QThreadPool supports executing the same QRunnable more than once 
+  by calling tryStart(this) from within QRunnable::run(). If autoDelete is 
+  enabled the QRunnable will be deleted when the last thread exits the 
+  run function. Calling start() multiple times with the same QRunnable 
+  when autoDelete is enabled creates a race condition and is not recommended.
+  */
+  mUdpMasterListener = udpmasterlistener;
+  setAutoDelete(false); // stick around after calling run()
+  //mNetks = new NetKS;
+  //mNetks->play();
+}
+
+
+//*******************************************************************************
+JackTripWorker::~JackTripWorker()
+{
+  delete mUdpMasterListener;
+  
+}
+
+
+//*******************************************************************************
+void JackTripWorker::setJackTrip(int id, uint32_t client_address,
+                                uint16_t server_port, uint16_t client_port,
+                                int num_channels)
+{
+  { //Start Spawning, so lock mSpawning
+    QMutexLocker locker(&mMutex);
+    mSpawning = true;
+  }
+  mID = id;
+  // Set the jacktrip address and ports
+  mClientAddress.setAddress(client_address);
+  mServerPort = server_port;
+  mClientPort = client_port;
+  mNumChans = num_channels;
+}
+
+
+//*******************************************************************************
+void JackTripWorker::run()
+{
+  /*
+    NOTE: This is the message that qt prints when an exception is thrown:
+    'Qt Concurrent has caught an exception thrown from a worker thread.
+    This is not supported, exceptions thrown in worker threads must be
+    caught before control returns to Qt Concurrent.'
+  */
+  
+  // Try catching any exceptions that come from JackTrip
+  try 
+    {
+      // Local event loop. this is necesary because QRunnables don't have their own as QThreads
+      QEventLoop event_loop;
+      
+      // Create and setup JackTrip Object
+      JackTrip jacktrip(JackTrip::CLIENT, JackTrip::UDP, mNumChans, 2);
+      jacktrip.setPeerAddress( mClientAddress.toString().toLatin1().data() );
+      jacktrip.setBindPorts(mServerPort);
+      jacktrip.setPeerPorts(mClientPort-1);
+
+      // Connect signals and slots
+      // -------------------------
+      QObject::connect(&jacktrip, SIGNAL(signalNoUdpPacketsForSeconds()),
+                      &jacktrip, SLOT(slotStopProcesses()), Qt::QueuedConnection);
+
+      // Connection to terminate the local eventloop when jacktrip is done
+      QObject::connect(&jacktrip, SIGNAL(signalProcessesStopped()),
+                      &event_loop, SLOT(quit()), Qt::QueuedConnection);
+
+      // Karplus Strong String
+      NetKS netks;
+      jacktrip.appendProcessPlugin(&netks);
+      // Play the String
+      QTimer timer;
+      QObject::connect(&timer, SIGNAL(timeout()), &netks, SLOT(exciteString()),
+                      Qt::QueuedConnection);
+      timer.start(300);
+      
+      // Start Threads and event loop
+      jacktrip.start();
+      
+      { // Thread is already spawning, so release the lock
+       QMutexLocker locker(&mMutex);
+       mSpawning = false;
+      }
+      
+      event_loop.exec(); // Excecution will block here until exit() the QEventLoop
+      //--------------------------------------------------------------------------
+      
+      // wait for jacktrip to be done before exiting the Worker Thread
+      jacktrip.wait();
+      
+    }
+  catch ( const std::exception & e )
+    {
+      std::cerr << "Couldn't send thread to the Pool" << endl;
+      std::cerr << e.what() << endl;
+      std::cerr << gPrintSeparator << endl;
+    }
+  
+  mUdpMasterListener->releasePort(mID);
+  { 
+    // Thread is already spawning, so release the lock
+    QMutexLocker locker(&mMutex);
+    mSpawning = false;
+  }
+
+  cout << "JackTrip ID = " << mID << " released from the THREAD POOL" << endl;
+  cout << gPrintSeparator << endl;
+}
+
+
+//*******************************************************************************
+bool JackTripWorker::isSpawning()
+{
+  QMutexLocker locker(&mMutex);
+  return mSpawning;
+}
diff --git a/src/JackTripWorker.h b/src/JackTripWorker.h
new file mode 100644 (file)
index 0000000..8df371e
--- /dev/null
@@ -0,0 +1,122 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTripWorker.h
+ * \author Juan-Pablo Caceres
+ * \date September 2008
+ */
+
+#ifndef __JACKTRIPWORKER_H__
+#define __JACKTRIPWORKER_H__
+
+#include <iostream>
+
+#include <QThreadPool>
+#include <QObject>
+#include <QEventLoop>
+#include <QHostAddress>
+#include <QMutex>
+
+#include "jacktrip_types.h"
+
+class JackTrip; // forward declaration
+class UdpMasterListener; // forward declaration
+
+
+/** \brief Prototype of the worker class that will be cloned through sending threads to the 
+ * Thread Pool
+ *
+ * This class can be send to the ThreadPool using the start() method. Each time 
+ * it is sent, it'll became "independent" of the prototype, which means
+ * that the prototype state can be changed, and used to send and start
+ * another thread into the pool. setAutoDelete must be set to false
+ * in order for this to work.
+ */
+// Note that it is not possible to start run() as an event loop. That has to be implemented
+// inside a QThread
+class JackTripWorker : public QObject, public QRunnable
+{
+  Q_OBJECT; // QRunnable is not a QObject, so I have to inherit from QObject as well
+  
+public:
+  /// \brief The class constructor
+  JackTripWorker(UdpMasterListener* udpmasterlistener);
+
+  /// \brief The class destructor
+  virtual ~JackTripWorker();
+  
+  /** \brief Implements the Thread Loop.
+   * To start the thread, call start() ( DO NOT CALL run() ). 
+   */
+  void run();
+
+  /** \brief Check if the Thread is Spawning
+   * \return true is it is spawning, false if it's already running
+   */
+  bool isSpawning();
+
+  /** \brief Sets the JackTripWorker properties
+   * \param id ID number
+   * \param address 
+   */
+  void setJackTrip(int id, uint32_t client_address,
+                  uint16_t server_port, uint16_t client_port,
+                  int num_channels);
+
+
+private slots:
+  void slotTest()
+  {
+    std::cout << "--- JackTripWorker TEST SLOT ---" << std::endl;
+  }
+
+
+private:
+
+  UdpMasterListener* mUdpMasterListener; ///< Master Listener Socket
+  QHostAddress mClientAddress; ///< Client Address
+  uint16_t mServerPort; ///< Server Ephemeral Incomming Port to use with Client
+
+  /// Client Outgoing Port. By convention, the receving port will be <tt>mClientPort -1</tt> 
+  uint16_t mClientPort;
+
+  /// Thread spawning internal lock.
+  /// If true, the prototype is working on creating (spawning) a new thread
+  volatile bool mSpawning;
+  QMutex mMutex; ///< Mutex to protect mSpawning
+
+  int mID; ///< ID thread number
+  int mNumChans; ///< Number of Channels
+};
+
+
+#endif //__JACKTRIPWORKER_H__
diff --git a/src/JackTripWorkerMessages.h b/src/JackTripWorkerMessages.h
new file mode 100644 (file)
index 0000000..e3bef9a
--- /dev/null
@@ -0,0 +1,75 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTripWorkerMessages.h
+ * \author Juan-Pablo Caceres
+ * \date October 2008
+ */
+
+#ifndef __JACKTRIPWORKERMESSAGES_H__
+#define __JACKTRIPWORKERMESSAGES_H__
+
+#include <QObject>
+#include <QTimer>
+
+#include <iostream>
+
+class JackTripWorkerMessages : public QObject
+{
+  Q_OBJECT;
+
+public:
+  JackTripWorkerMessages() {};
+  virtual ~JackTripWorkerMessages() {};
+
+  void play()
+  {
+    std::cout << "********** PALYING ***********************************" << std::endl;
+    QTimer *timer = new QTimer(this);
+    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(slotTest()), Qt::QueuedConnection);
+    timer->start(300);
+  }
+
+public slots:
+  void slotTest()
+  {
+    std::cout << "---JackTripWorkerMessages slotTest()---" << std::endl;
+  }
+signals:
+  void signalTest();
+  /// Signal to stop the event loop inside the JackTripWorker Thread
+  void signalStopEventLoop();
+
+};
+
+#endif //__JACKTRIPWORKERMESSAGES_H__
diff --git a/src/LoopBack.cpp b/src/LoopBack.cpp
new file mode 100644 (file)
index 0000000..f22197b
--- /dev/null
@@ -0,0 +1,54 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file LoopBack.cpp
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+
+#include "LoopBack.h"
+#include "jacktrip_types.h"
+
+#include <cstring> // for memcpy
+
+
+//*******************************************************************************
+void LoopBack::compute(int nframes, float** inputs, float** outputs)
+{
+  for ( int i = 0; i < getNumInputs(); i++ ) {
+    // Everything that comes out, copy back to inputs
+    //memcpy(inputs[i], outputs[i], sizeof(sample_t) * nframes);
+    memcpy(outputs[i], inputs[i], sizeof(sample_t) * nframes);
+  }
+}
+
diff --git a/src/LoopBack.h b/src/LoopBack.h
new file mode 100644 (file)
index 0000000..c25de27
--- /dev/null
@@ -0,0 +1,70 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file LoopBack.h
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+
+/** \brief Connect Inputs to Outputs
+ *
+ */
+#ifndef __LOOPBACK_H__
+#define __LOOPBACK_H__
+
+#include "ProcessPlugin.h"
+
+
+/** \brief This Class just copy audio from its inputs to its outputs.
+ *
+ * It can be use to do loopback without the need to externally connect channels
+ * in JACK. Note that if you <EM>do</EM> connect the channels in jack, you'll
+ * be effectively multiplying the signal by 2.
+ */
+class LoopBack : public ProcessPlugin
+{
+public:
+  /// \brief The class constructor sets the number of channels to connect as loopback
+  LoopBack(int numchans) { mNumChannels = numchans; };
+  /// \brief The class destructor
+  virtual ~LoopBack() {};
+
+  virtual int getNumInputs() { return(mNumChannels); };
+  virtual int getNumOutputs() { return(mNumChannels); };
+  virtual void compute(int nframes, float** inputs, float** outputs);
+
+private:
+  int mNumChannels;
+};
+
+#endif
diff --git a/src/NetKS.h b/src/NetKS.h
new file mode 100644 (file)
index 0000000..2d09c4b
--- /dev/null
@@ -0,0 +1,137 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file JackTrip.h
+ * \author Juan-Pablo Caceres
+ * \date October 2008
+ */
+
+#ifndef __NETKS_H__
+#define __NETKS_H__
+
+#include <iostream>
+#include <unistd.h>
+
+#include <QTimer>
+
+#include "ProcessPlugin.h"
+
+/** \brief A simple (basic) network Karplus Strong.
+ *
+ * This plugin creates a one channel network karplus strong.
+ */
+class NetKS : public ProcessPlugin
+{
+  Q_OBJECT;
+
+
+public:
+  /*
+  void play()
+  {
+    std::cout << "********** PALYING ***********************************" << std::endl;
+    QTimer *timer = new QTimer(this);
+    QObject::connect(timer, SIGNAL(timeout()),  this, SLOT(exciteString()));
+    timer->start(300);
+  }
+  */
+
+private slots:
+
+  /// \brief Stlot to excite (play) the string
+  void exciteString()
+  {
+    std::cout << "========= EXTICING STRING ===========" << std::endl;
+    fbutton0 = 1.0;
+    //std::cout << fbutton0 << std::endl;
+    usleep(280000); /// \todo Define this number based on the sampling rate and buffer size
+    fbutton0 = 0.0;
+    //std::cout << fbutton0 << std::endl;
+  }
+
+  //=========== FROM FAUST ===================================================
+  private:
+       float   fbutton0;
+       float   fVec0[2];
+       float   fRec0[2];
+       int     iRec1[2];
+       float   fVec1[2];
+  public:
+       virtual int getNumInputs()      { return 1; }
+       virtual int getNumOutputs()     { return 1; }
+  static void classInit(int /*samplingFreq*/) {}
+       virtual void instanceInit(int samplingFreq) {
+               fSamplingFreq = samplingFreq;
+               fbutton0 = 0.0;
+               for (int i=0; i<2; i++) fVec0[i] = 0;
+               for (int i=0; i<2; i++) fRec0[i] = 0;
+               for (int i=0; i<2; i++) iRec1[i] = 0;
+               for (int i=0; i<2; i++) fVec1[i] = 0;
+       }
+       virtual void init(int samplingFreq) {
+               classInit(samplingFreq);
+               instanceInit(samplingFreq);
+       }
+  /*
+       virtual void buildUserInterface(UI* interface) {
+               interface->openVerticalBox("excitator");
+               interface->addButton("play", &fbutton0);
+               interface->closeBox();
+       }
+  */
+       virtual void compute (int count, float** input, float** output) {
+               float* input0 = input[0];
+               float* output0 = output[0];
+               float fSlow0 = fbutton0;
+               for (int i=0; i<count; i++) {
+                       fVec0[0] = fSlow0;
+                       fRec0[0] = ((((fSlow0 - fVec0[1]) > 0.000000f) + fRec0[1]) - (3.333333e-03f * (fRec0[1] > 0.000000f)));
+                       iRec1[0] = (12345 + (1103515245 * iRec1[1]));
+                       float fTemp0 = ((4.190951e-10f * iRec1[0]) * (fRec0[0] > 0.000000f));
+                       float fTemp1 = input0[i];
+                       fVec1[0] = (fTemp1 + fTemp0);
+                       output0[i] = (0.500000f * ((fTemp0 + fTemp1) + fVec1[1]));
+                       // post processing
+                       fVec1[1] = fVec1[0];
+                       iRec1[1] = iRec1[0];
+                       fRec0[1] = fRec0[0];
+                       fVec0[1] = fVec0[0];
+               }
+       }
+
+  //============================================================================
+
+};
+
+
+#endif // __NETKS_H__
+
diff --git a/src/PacketHeader.cpp b/src/PacketHeader.cpp
new file mode 100644 (file)
index 0000000..1a37556
--- /dev/null
@@ -0,0 +1,265 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file PacketHeader.cpp
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+#include "PacketHeader.h"
+#include "JackTrip.h"
+
+#include <sys/time.h>
+#include <cstdlib>
+#include <iostream>
+#include <stdexcept>
+
+using std::cout; using std::endl;
+
+
+//#######################################################################
+//####################### PacketHeader ##################################
+//#######################################################################
+//***********************************************************************
+PacketHeader::PacketHeader(JackTrip* jacktrip) : 
+  mSeqNumber(0), mJackTrip(jacktrip)
+{}
+
+
+//***********************************************************************
+uint64_t PacketHeader::usecTime()
+{
+  struct timeval tv;
+  gettimeofday (&tv, NULL);
+  return ( (tv.tv_sec * 1000000)  + // seconds
+          (tv.tv_usec) );  // plus the microseconds. Type suseconds_t, range [-1, 1000000]
+}
+
+
+
+
+//#######################################################################
+//####################### DefaultHeader #################################
+//#######################################################################
+//***********************************************************************
+DefaultHeader::DefaultHeader(JackTrip* jacktrip) : 
+  PacketHeader(jacktrip), mJackTrip(jacktrip)
+{
+  mHeader.TimeStamp = 0;
+  mHeader.SeqNumber = 0;  
+  mHeader.BufferSize = 0; 
+  mHeader.SamplingRate = 0;
+  mHeader.BitResolution = 0;
+  mHeader.NumInChannels = 0;
+  mHeader.NumOutChannels = 0;
+  //mHeader.Dummy = 0;
+}
+
+
+//***********************************************************************
+void DefaultHeader::fillHeaderCommonFromAudio()
+{
+  mHeader.BufferSize = mJackTrip->getBufferSizeInSamples();
+  mHeader.SamplingRate = mJackTrip->getSampleRateType ();
+  mHeader.NumInChannels = mJackTrip->getNumInputChannels();
+  mHeader.BitResolution = mJackTrip->getAudioBitResolution();
+  mHeader.NumOutChannels = mJackTrip->getNumOutputChannels();
+  //mHeader.SeqNumber = 0;
+  mHeader.TimeStamp = PacketHeader::usecTime();
+  //cout << mHeader.TimeStamp << endl;
+  //printHeader();
+}
+
+
+//***********************************************************************
+void DefaultHeader::checkPeerSettings(int8_t* full_packet)
+{
+  bool error = false;
+  
+  DefaultHeaderStruct* peer_header;
+  peer_header =  reinterpret_cast<DefaultHeaderStruct*>(full_packet);
+
+  // Check Buffer Size
+  if ( peer_header->BufferSize != mHeader.BufferSize ) 
+    {
+      std::cerr << "ERROR: Peer Buffer Size is  : " << peer_header->BufferSize << endl;
+      std::cerr << "       Local Buffer Size is : " << mHeader.BufferSize << endl;
+      std::cerr << "Make sure both machines use same buffer size" << endl;
+      std::cerr << gPrintSeparator << endl;
+      error = true;
+    }
+
+  // Check Sampling Rate
+  if ( peer_header->SamplingRate != mHeader.SamplingRate ) 
+    {
+      std::cerr << "ERROR: Peer Sampling Rate is  : " << 
+       JackAudioInterface::getSampleRateFromType
+       ( static_cast<JackAudioInterface::samplingRateT>(peer_header->SamplingRate) ) << endl;
+      std::cerr << "       Local Sampling Rate is  : " << 
+       JackAudioInterface::getSampleRateFromType
+       ( static_cast<JackAudioInterface::samplingRateT>(mHeader.SamplingRate) ) << endl;
+      std::cerr << "Make sure both machines use the same Sampling Rate" << endl;
+      std::cerr << gPrintSeparator << endl;
+      error = true;
+    }
+
+  // Check Audio Bit Resolution
+  if ( peer_header->BitResolution != mHeader.BitResolution ) 
+    {
+      std::cerr << "ERROR: Peer Audio Bit Resolution is  : " 
+               << static_cast<int>(peer_header->BitResolution) << endl;
+      std::cerr << "       Local Audio Bit Resolution is : "
+               << static_cast<int>(mHeader.BitResolution) << endl;
+      std::cerr << "Make sure both machines use the same Bit Resolution" << endl;
+      std::cerr << gPrintSeparator << endl;
+      error = true;
+    }
+
+  // Exit program if error
+  if (error) 
+    {
+      //std::cerr << "Exiting program..." << endl;
+      //std::exit(1);
+      throw std::logic_error("Local and Peer Settings don't match");
+    }
+  /// \todo Check number of channels and other parameters
+}
+
+
+//***********************************************************************
+void DefaultHeader::printHeader() const
+{
+  cout << "Default Packet Header:" << endl;
+  cout << "Buffer Size               = " << static_cast<int>(mHeader.BufferSize) << endl;
+  // Get the sample rate in Hz form the JackAudioInterface::samplingRateT
+  int sample_rate = 
+    JackAudioInterface::getSampleRateFromType
+    ( static_cast<JackAudioInterface::samplingRateT>(mHeader.SamplingRate) );
+  cout << "Sampling Rate             = " << sample_rate << endl;
+  cout << "Audio Bit Resolutions     = " << static_cast<int>(mHeader.BitResolution) << endl;
+  cout << "Number of Input Channels  = " << static_cast<int>(mHeader.NumInChannels) << endl;
+  cout << "Number of Output Channels = " << static_cast<int>(mHeader.NumOutChannels) << endl;
+  cout << "Sequence Number           = " << static_cast<int>(mHeader.SeqNumber) << endl;
+  cout << "Time Stamp                = " << mHeader.TimeStamp << endl;
+  cout << gPrintSeparator << endl;
+  cout << sizeof(mHeader) << endl;
+}
+
+
+//***********************************************************************
+uint16_t DefaultHeader::getPeerSequenceNumber(int8_t* full_packet) const
+{
+  DefaultHeaderStruct* peer_header;
+  peer_header =  reinterpret_cast<DefaultHeaderStruct*>(full_packet);
+  return peer_header->SeqNumber;
+}
+
+
+
+
+
+
+
+
+//#######################################################################
+//####################### JamLinkHeader #################################
+//#######################################################################
+//***********************************************************************
+JamLinkHeader::JamLinkHeader(JackTrip* jacktrip) :
+  PacketHeader(jacktrip), mJackTrip(jacktrip)
+{
+  mHeader.Common = 0;
+  mHeader.SeqNumber = 0;
+  mHeader.TimeStamp = 0;
+}
+
+
+//***********************************************************************
+void JamLinkHeader::fillHeaderCommonFromAudio()
+{
+  // Check number of channels
+  int num_inchannels = mJackTrip->getNumInputChannels();
+  if ( num_inchannels != 1 ) {
+    //std::cerr << "ERROR: JamLink only support ONE channel. Run JackTrip using only one channel"
+    //       << endl;
+    //std::exit(1);
+    throw std::logic_error("JamLink only support ONE channel. Run JackTrip using only one channel");
+  }
+  
+  // Sampling Rate
+  int rate_type = mJackTrip->getSampleRateType();
+  if ( rate_type != JackAudioInterface::SR48 ) {
+    throw std::logic_error("ERROR: JamLink only support 48kHz for communication with JackTrip at the moment.");
+  }
+
+  // Check Buffer Size
+  int buf_size = mJackTrip->getBufferSizeInSamples();
+  if ( buf_size != 64 )
+    {
+      throw std::logic_error("ERROR: JamLink only support 64 buffer size for communication with JackTrip at the moment.");
+    }
+
+  mHeader.Common = (ETX_MONO | ETX_16BIT | ETX_XTND) + 64;
+  switch (rate_type)
+    {
+    case JackAudioInterface::SR48 :
+      mHeader.Common = (mHeader.Common | ETX_48KHZ);
+      break;
+    case JackAudioInterface::SR44 :
+      mHeader.Common = (mHeader.Common | ETX_44KHZ);
+      break;
+    case JackAudioInterface::SR32 :
+      mHeader.Common = (mHeader.Common | ETX_32KHZ);
+      break;
+    case JackAudioInterface::SR22 :
+      mHeader.Common = (mHeader.Common | ETX_22KHZ);
+      break;
+    default:
+      //std::cerr << "ERROR: Sample rate not supported by JamLink" << endl;
+      //std::exit(1);
+      throw std::out_of_range("Sample rate not supported by JamLink");
+      break;
+    }
+}
+
+
+
+
+
+
+//#######################################################################
+//####################### EmptyHeader #################################
+//#######################################################################
+//***********************************************************************
+EmptyHeader::EmptyHeader(JackTrip* jacktrip) :
+  PacketHeader(jacktrip), mJackTrip(jacktrip)
+{}
diff --git a/src/PacketHeader.h b/src/PacketHeader.h
new file mode 100644 (file)
index 0000000..73cf979
--- /dev/null
@@ -0,0 +1,292 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file PacketHeader.h
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+#ifndef __PACKETHEADER_H__
+#define __PACKETHEADER_H__
+
+#include <iostream>
+#include <tr1/memory> // for shared_ptr
+#include <cstring>
+
+#include "jacktrip_types.h"
+#include "jacktrip_globals.h"
+class JackTrip; // Forward Declaration
+
+
+/// \brief Abstract Header Struct, Header Stucts should subclass it
+struct HeaderStruct{};
+
+/// \brief Default Header Struct
+struct DefaultHeaderStruct : public HeaderStruct
+{
+public:
+  // watch out for alignment...
+  uint64_t TimeStamp; ///< Time Stamp
+  uint16_t SeqNumber; ///< Sequence Number
+  uint16_t BufferSize; ///< Buffer Size in Samples
+  uint8_t  SamplingRate; ///< Sampling Rate in JackAudioInterface::samplingRateT
+  uint8_t BitResolution; ///< Audio Bit Resolution
+  uint8_t  NumInChannels; ///< Number of Input Channels
+  uint8_t  NumOutChannels; ///<  Number of Output Channels
+  //uint8_t  Dummy; ///< Dummy value to byte padding alignment 
+};
+
+//---------------------------------------------------------
+//JamLink UDP Header:
+/************************************************************************/
+/* values for the UDP stream type                                       */
+/* streamType is a 16-bit value at the head of each UDP stream          */
+/* Its bit map is as follows:  (b15-msb)                                */
+/* B15:reserved, B14:extended header, B13 Stereo, B12 not 16-bit        */
+/* B11-B9: 0-48 Khz, 1-44 Khz, 2-32 Khz, 3-24 Khz,                      */
+/*         4-22 Khz, 5-16 Khz, 6-11 Khz, 7-8 Khz                        */      
+/* B8-0: Samples in packet                                              */
+/************************************************************************/
+const unsigned short ETX_RSVD = (0<<15);
+const unsigned short ETX_XTND = (1<<14);
+const unsigned short ETX_STEREO = (1<<13);
+const unsigned short ETX_MONO = (0<<13);
+const unsigned short ETX_16BIT = (0<<12);
+//inline unsigned short ETX_RATE_MASK(const unsigned short a) { a&(0x7<<9); }
+const unsigned short ETX_48KHZ = (0<<9);
+const unsigned short ETX_44KHZ = (1<<9);
+const unsigned short ETX_32KHZ = (2<<9);
+const unsigned short ETX_24KHZ = (3<<9);
+const unsigned short ETX_22KHZ = (4<<9);
+const unsigned short ETX_16KHZ = (5<<9);
+const unsigned short ETX_11KHZ = (6<<9);
+const unsigned short ETX_8KHZ  = (7<<9);
+// able to express up to 512 SPP
+//inline unsigned short  ETX_SPP(const unsigned short a) { (a&0x01FF); }
+
+/// \brief JamLink Header Struct
+struct JamLinkHeaderStuct : public HeaderStruct
+{
+  // watch out for alignment -- need to be on 4 byte chunks
+  uint16_t Common; ///< Common part of the header, 16 bit
+  uint16_t SeqNumber; ///< Sequence Number
+  uint32_t TimeStamp; ///< Time Stamp
+};
+
+
+//#######################################################################
+//####################### PacketHeader ##################################
+//#######################################################################
+/** \brief Base class for header type. Subclass this struct to
+ * create a new header.
+ */
+class PacketHeader
+{
+public:
+  /// \brief The class Constructor
+  PacketHeader(JackTrip* jacktrip);
+  /// \brief The class Destructor
+  virtual ~PacketHeader() {};
+  
+  /** \brief Return a time stamp in microseconds
+   * \return Time stamp: microseconds since midnight (0 hour), January 1, 1970
+   */
+  static uint64_t usecTime();
+
+  /// \todo Implement this using a JackTrip Method (Mediator) member instead of the 
+  /// reference to JackAudio
+  virtual void fillHeaderCommonFromAudio() = 0;
+
+  /* \brief Parse the packet header and take appropriate measures (like change settings, or 
+   * quit the program if peer settings don't match)
+   */
+  virtual void parseHeader() = 0;
+
+  virtual void checkPeerSettings(int8_t* full_packet) = 0;
+  virtual uint16_t getPeerSequenceNumber(int8_t* full_packet) const = 0;
+
+  /* \brief Increase sequence number for counter, a 16bit number
+   */
+  virtual void increaseSequenceNumber()
+  {
+    mSeqNumber++;
+  };
+
+  /* \brief Returns the current sequence number
+   * \return 16bit Sequence number
+   */
+  virtual uint16_t getSequenceNumber() const
+  {
+    return mSeqNumber;
+  }
+
+  /* \brief Get the header size in bytes
+   */
+  virtual int getHeaderSizeInBytes() const = 0;
+
+
+  virtual void putHeaderInPacketBaseClass(int8_t* full_packet,
+                                      const HeaderStruct& header_struct)
+  {
+    std::memcpy(full_packet, reinterpret_cast<const void*>(&header_struct),
+               getHeaderSizeInBytes() );
+  };
+
+  /* \brief Put the header in buffer pointed by full_packet
+   * \param full_packet Pointer to full packet (audio+header). Size must be
+   * sizeof(header part) + sizeof(audio part)
+   */
+  virtual void putHeaderInPacket(int8_t* full_packet) = 0;
+
+private:
+  uint16_t mSeqNumber;
+  JackTrip* mJackTrip; ///< JackTrip mediator class
+};
+
+
+
+
+//#######################################################################
+//####################### DefaultHeader #################################
+//#######################################################################
+/** \brief Default Header
+ */
+class DefaultHeader : public PacketHeader
+{
+public:
+  /*
+  //----------STRUCT-----------------------------------------
+  /// \brief Default Header Struct
+  struct DefaultHeaderStruct
+  {
+    // watch out for alignment...
+    uint64_t TimeStamp; ///< Time Stamp
+    uint16_t SeqNumber; ///< Sequence Number
+    uint16_t BufferSize; ///< Buffer Size in Samples
+    uint8_t  SamplingRate; ///< Sampling Rate in JackAudioInterface::samplingRateT
+    uint8_t  NumInChannels; ///< Number of Input Channels
+    uint8_t  NumOutChannels; ///<  Number of Output Channels
+    // uint8_t BitResolution; ///< \todo implement this part
+  };
+  //---------------------------------------------------------
+  */
+  DefaultHeader(JackTrip* jacktrip);
+  virtual ~DefaultHeader() {};
+  virtual void fillHeaderCommonFromAudio();
+  virtual void parseHeader() {};
+  virtual void checkPeerSettings(int8_t* full_packet);
+  virtual void increaseSequenceNumber()
+  {
+    mHeader.SeqNumber++;
+    //std::cout << "Sequence Number = " << static_cast<int>(mHeader.SeqNumber) << std::endl;
+  };
+  virtual uint16_t getSequenceNumber() const
+  {
+    return mHeader.SeqNumber;
+  }
+  virtual uint16_t getPeerSequenceNumber(int8_t* full_packet) const;
+  virtual int getHeaderSizeInBytes() const { return sizeof(mHeader); };
+  virtual void putHeaderInPacket(int8_t* full_packet)
+  {
+    putHeaderInPacketBaseClass(full_packet, mHeader);
+    //std::memcpy(full_packet, reinterpret_cast<const void*>(&mHeader),
+    // getHeaderSizeInBytes() );
+  };
+  void printHeader() const;
+
+private:
+  //DefaultHeaderStruct mHeader; ///< Header Struct
+  DefaultHeaderStruct mHeader;///< Default Header Struct
+  JackTrip* mJackTrip; ///< JackTrip mediator class
+};
+
+
+
+
+//#######################################################################
+//####################### JamLinkHeader #################################
+//#######################################################################
+
+/** \brief JamLink Header
+ */
+class JamLinkHeader : public PacketHeader
+{
+public:
+  
+  JamLinkHeader(JackTrip* jacktrip);
+  virtual ~JamLinkHeader() {};
+
+  virtual void fillHeaderCommonFromAudio();
+  virtual void parseHeader() {};
+  virtual void checkPeerSettings(int8_t* /*full_packet*/) {}
+  virtual uint16_t getPeerSequenceNumber(int8_t* /*full_packet*/) const { /*\todo IMPLEMENT*/ return 0; }
+  virtual void increaseSequenceNumber() {};
+  virtual int getHeaderSizeInBytes() const { return sizeof(mHeader); };
+  virtual void putHeaderInPacket(int8_t* full_packet)
+  {
+    putHeaderInPacketBaseClass(full_packet, mHeader);
+  };
+
+private:
+  JamLinkHeaderStuct mHeader; ///< JamLink Header Struct
+  JackTrip* mJackTrip; ///< JackTrip mediator class
+};
+
+
+
+//#######################################################################
+//####################### EmptyHeader #################################
+//#######################################################################
+
+/** \brief Empty Header to use with systems that don't include a header.
+ */
+class EmptyHeader : public PacketHeader
+{
+public:
+  
+  EmptyHeader(JackTrip* jacktrip);
+  virtual ~EmptyHeader() {};
+
+  virtual void fillHeaderCommonFromAudio() {};
+  virtual void parseHeader() {};
+  virtual void checkPeerSettings(int8_t* /*full_packet*/) {}
+  virtual uint16_t getPeerSequenceNumber(int8_t* /*full_packet*/) const { return 0; /*\todo IMPLEMENT*/}
+  virtual void increaseSequenceNumber() {};
+  virtual int getHeaderSizeInBytes() const { return 0; };
+  virtual void putHeaderInPacket(int8_t* /*full_packet*/) {};
+
+private:
+  JackTrip* mJackTrip; ///< JackTrip mediator class
+};
+
+
+#endif //__PACKETHEADER_H__
diff --git a/src/ProcessPlugin.cpp b/src/ProcessPlugin.cpp
new file mode 100644 (file)
index 0000000..be26a31
--- /dev/null
@@ -0,0 +1,31 @@
+//#include "ProcessPlugin.h"
+
+/*
+//----------------------------------------------------------------------------
+// Jack Callbacks 
+//----------------------------------------------------------------------------
+
+int srate(jack_nframes_t nframes, void *arg)
+{
+  printf("the sample rate is now %u/sec\n", nframes);
+  return 0;
+}
+
+void jack_shutdown(void *arg)
+{
+  std::cout << "" << std::endl; 
+  std::exit(1);
+}
+
+int process (jack_nframes_t nframes, void *arg)
+{
+  for (int i = 0; i < gNumInChans; i++) {
+    gInChannel[i] = (float *)jack_port_get_buffer(input_ports[i], nframes);
+  }
+  for (int i = 0; i < gNumOutChans; i++) {
+    gOutChannel[i] = (float *)jack_port_get_buffer(output_ports[i], nframes);
+  }
+  DSP.compute(nframes, gInChannel, gOutChannel);
+  return 0;
+}
+*/
diff --git a/src/ProcessPlugin.h b/src/ProcessPlugin.h
new file mode 100644 (file)
index 0000000..70533c8
--- /dev/null
@@ -0,0 +1,81 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file ProcessPlugin.h
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+#ifndef __PROCESSPLUGIN_H__
+#define __PROCESSPLUGIN_H__
+
+#include <jack/jack.h>
+#include <QObject>
+
+/** \brief Interface for the process plugins to add to the JACK callback process in 
+ * JackAudioInterface
+ *
+ * This class contains the same methods of the FAUST dsp class. A mydsp class can inherit from
+ * this class the same way it inherits from dsp. Subclass should implement all methods
+ * except init, which is optional for processing that are sampling rate dependent or 
+ * that need specific initialization.
+ */
+class ProcessPlugin : public QObject
+{
+public:
+
+  /// \brief The Class Constructor
+  ProcessPlugin() {};
+  /// \brief The Class Destructor
+  virtual ~ProcessPlugin() {};
+  
+  /// \brief Return Number of Input Channels
+  virtual int getNumInputs() = 0;
+  /// \brief Return Number of Output Channels
+  virtual int getNumOutputs() = 0;
+
+  //virtual void buildUserInterface(UI* interface) = 0;
+
+  /** \brief Do proper Initialization of members and class instances. By default this
+   * initializes the Sampling Frequency. If a class instance depends on the
+   * sampling frequency, it should be initialize here.
+   */
+  virtual void init(int samplingRate) { fSamplingFreq = samplingRate; };
+  
+  /// \brief Compute process
+  virtual void compute(int nframes, float** inputs, float** outputs) = 0;
+  
+protected:
+  int fSamplingFreq; ///< Faust Data member, Sampling Rate
+};
+
+#endif
diff --git a/src/RingBuffer.cpp b/src/RingBuffer.cpp
new file mode 100644 (file)
index 0000000..a9e746c
--- /dev/null
@@ -0,0 +1,250 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file RingBuffer.cpp
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+
+#include "RingBuffer.h"
+
+#include <iostream>
+#include <cstring>
+#include <cstdlib>
+#include <stdexcept>
+
+using std::cout; using std::endl;
+
+
+//*******************************************************************************
+RingBuffer::RingBuffer(int SlotSize, int NumSlots) : 
+  mSlotSize(SlotSize),
+  mNumSlots(NumSlots),
+  mTotalSize(mSlotSize*mNumSlots),
+  mReadPosition(0),
+  mWritePosition(0),
+  mFullSlots(0),
+  mRingBuffer(new int8_t[mTotalSize]),
+  mLastReadSlot(new int8_t[mSlotSize])
+{
+  //QMutexLocker locker(&mMutex); // lock the mutex  
+  
+  // Verify if there's enough space to for the buffers
+  if ( (mRingBuffer == NULL) || (mLastReadSlot == NULL) ) {
+    //std::cerr << "ERROR: RingBuffer out of memory!" << endl;
+    //std::cerr << "Exiting program..." << endl;
+    //std::exit(1);
+    throw std::length_error("RingBuffer out of memory!");
+  }
+
+  // Set the buffers to zeros
+  /*
+  for (int i=0; i<mTotalSize; i++) {
+    mRingBuffer[i] = 0;    // Initialize all elements to zero.
+  }
+  */
+  std::memset(mRingBuffer, 0, mTotalSize); // set buffer to 0
+  /*
+  for (int i=0; i<mSlotSize; i++) {
+    mLastReadSlot[i] = 0;    // Initialize all elements to zero.
+  }
+  */
+  std::memset(mLastReadSlot, 0, mSlotSize); // set buffer to 0
+  
+  
+  // Advance write position to half of the RingBuffer
+  mWritePosition = ( (NumSlots/2) * SlotSize ) % mTotalSize;
+  // Udpate Full Slots accordingly
+  mFullSlots = (NumSlots/2);
+}
+
+
+//*******************************************************************************
+RingBuffer::~RingBuffer()
+{
+  delete[] mRingBuffer; // Free memory
+  mRingBuffer = NULL; // Clear to prevent using invalid memory reference
+  delete[] mLastReadSlot;
+  mLastReadSlot = NULL;
+}
+
+
+//*******************************************************************************
+void RingBuffer::insertSlotBlocking(const int8_t* ptrToSlot)
+{
+  QMutexLocker locker(&mMutex); // lock the mutex
+
+  // Check if there is space available to write a slot
+  // If the Ringbuffer is full, it waits for the bufferIsNotFull condition
+  while (mFullSlots == mNumSlots) {
+    //std::cout << "OUPUT OVERFLOW BLOCKING" << std::endl;
+    mBufferIsNotFull.wait(&mMutex);
+  }
+
+  // Copy mSlotSize bytes to mRingBuffer
+  std::memcpy(mRingBuffer+mWritePosition, ptrToSlot, mSlotSize);
+  // Update write position
+  mWritePosition = (mWritePosition+mSlotSize) % mTotalSize;
+  mFullSlots++; //update full slots
+  // Wake threads waitng for bufferIsNotFull condition
+  mBufferIsNotEmpty.wakeAll();
+}
+
+
+//*******************************************************************************
+void RingBuffer::readSlotBlocking(int8_t* ptrToReadSlot)
+{
+  QMutexLocker locker(&mMutex); // lock the mutex
+
+  // Check if there are slots available to read
+  // If the Ringbuffer is empty, it waits for the bufferIsNotEmpty condition
+  while (mFullSlots == 0) {
+    //std::cerr << "READ UNDER-RUN BLOCKING before" << endl;
+    mBufferIsNotEmpty.wait(&mMutex);
+  }
+  
+  // Copy mSlotSize bytes to ReadSlot
+  std::memcpy(ptrToReadSlot, mRingBuffer+mReadPosition, mSlotSize);
+  // Always save memory of the last read slot
+  std::memcpy(mLastReadSlot, mRingBuffer+mReadPosition, mSlotSize);
+  // Update write position
+  mReadPosition = (mReadPosition+mSlotSize) % mTotalSize;
+  mFullSlots--; //update full slots
+  // Wake threads waitng for bufferIsNotFull condition
+  mBufferIsNotFull.wakeAll();
+}
+
+
+//*******************************************************************************
+void RingBuffer::insertSlotNonBlocking(const int8_t* ptrToSlot)
+{
+  QMutexLocker locker(&mMutex); // lock the mutex
+
+  // Check if there is space available to write a slot
+  // If the Ringbuffer is full, it returns without writing anything
+  // and resets the buffer
+  /// \todo It may be better here to insert the slot anyways,
+  /// instead of not writing anything
+  if (mFullSlots == mNumSlots) {
+    //std::cout << "OUPUT OVERFLOW NON BLOCKING = " << mNumSlots << std::endl;
+    overflowReset();
+    return;
+  }
+  
+  // Copy mSlotSize bytes to mRingBuffer
+  std::memcpy(mRingBuffer+mWritePosition, ptrToSlot, mSlotSize);
+  // Update write position
+  mWritePosition = (mWritePosition+mSlotSize) % mTotalSize;
+  mFullSlots++; //update full slots
+  // Wake threads waitng for bufferIsNotFull condition
+  mBufferIsNotEmpty.wakeAll();
+}
+
+
+//*******************************************************************************
+void RingBuffer::readSlotNonBlocking(int8_t* ptrToReadSlot)
+{
+  QMutexLocker locker(&mMutex); // lock the mutex
+  
+  // Check if there are slots available to read
+  // If the Ringbuffer is empty, it returns a buffer of zeros and rests the buffer
+  if (mFullSlots == 0) {
+    // Returns a buffer of zeros if there's nothing to read
+    //std::cerr << "READ UNDER-RUN NON BLOCKING = " << mNumSlots << endl;
+    //std::memset(ptrToReadSlot, 0, mSlotSize);
+    setUnderrunReadSlot(ptrToReadSlot);
+    underrunReset();
+    return;
+  }
+  
+  // Copy mSlotSize bytes to ReadSlot
+  std::memcpy(ptrToReadSlot, mRingBuffer+mReadPosition, mSlotSize);
+  // Always save memory of the last read slot
+  std::memcpy(mLastReadSlot, mRingBuffer+mReadPosition, mSlotSize);
+  // Update write position
+  mReadPosition = (mReadPosition+mSlotSize) % mTotalSize;
+  mFullSlots--; //update full slots
+  // Wake threads waitng for bufferIsNotFull condition
+  mBufferIsNotFull.wakeAll();
+}
+
+
+//*******************************************************************************
+void RingBuffer::setUnderrunReadSlot(int8_t* ptrToReadSlot)
+{
+  std::memset(ptrToReadSlot, 0, mSlotSize);
+}
+
+
+//*******************************************************************************
+void RingBuffer::setMemoryInReadSlotWithLastReadSlot(int8_t* ptrToReadSlot)
+{
+  std::memcpy(ptrToReadSlot, mLastReadSlot, mSlotSize);
+}
+
+
+
+
+//*******************************************************************************
+// Under-run happens when there's nothing to read.
+void RingBuffer::underrunReset()
+{
+  // Advance the write pointer 1/2 the ring buffer
+  //mWritePosition = ( mReadPosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize;
+  //mWritePosition = ( mWritePosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize;
+  //mFullSlots += mNumSlots/2;
+  // There's nothing new to read, so we clear the whole buffer (Set the entire buffer to 0)
+  std::memset(mRingBuffer, 0, mTotalSize);
+}
+
+
+//*******************************************************************************
+// Over-flow happens when there's no space to write more slots.
+void RingBuffer::overflowReset()
+{
+  // Advance the read pointer 1/2 the ring buffer
+  //mReadPosition = ( mWritePosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize;
+  mReadPosition = ( mReadPosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize;
+  mFullSlots -= mNumSlots/2;
+}
+
+
+//*******************************************************************************
+void RingBuffer::debugDump() const
+{
+  cout << "mTotalSize = " << mTotalSize << endl;
+  cout << "mReadPosition = " << mReadPosition << endl;
+  cout << "mWritePosition = " << mWritePosition << endl;
+  cout <<  "mFullSlots = " << mFullSlots << endl;
+}
diff --git a/src/RingBuffer.h b/src/RingBuffer.h
new file mode 100644 (file)
index 0000000..e3cf986
--- /dev/null
@@ -0,0 +1,142 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file RingBuffer.h
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+#ifndef __RINGBUFFER_H__
+#define __RINGBUFFER_H__
+
+#include <QWaitCondition>
+#include <QMutex>
+#include <QMutexLocker>
+
+#include "jacktrip_types.h"
+
+
+/** \brief Provides a ring-buffer (or circular-buffer) that can be written to and read from
+ * asynchronously (blocking) or synchronously (non-blocking).
+ *
+ * The RingBuffer is an array of \b NumSlots slots of memory
+ * each of which is of size \b SlotSize bytes (8-bits). Slots can be read and 
+ * written asynchronously/synchronously by multiple threads.
+ */
+class RingBuffer
+{
+public:
+
+  /** \brief The class constructor
+   * \param SlotSize Size of one slot in bytes
+   * \param NumSlots Number of slots
+   */
+  RingBuffer(int SlotSize, int NumSlots);
+
+  /** \brief The class destructor
+   */
+  virtual ~RingBuffer();
+  
+  /** \brief Insert a slot into the RingBuffer from ptrToSlot. This method will block until
+   * there's space in the buffer.
+   *
+   * The caller is responsible to make sure sizeof(WriteSlot) = SlotSize. This
+   * method should be use when the caller can block against its output, like 
+   * sending/receiving UDP packets. It shouldn't be used by audio. For that, use the
+   * insertSlotNonBlocking.
+   * \param ptrToSlot Pointer to slot to insert into the RingBuffer
+   */
+  void insertSlotBlocking(const int8_t* ptrToSlot);
+  
+  /** \brief Read a slot from the RingBuffer into ptrToReadSlot. This method will block until
+   * there's space in the buffer.
+   *
+   * The caller is responsible to make sure sizeof(ptrToReadSlot) = SlotSize. This
+   * method should be use when the caller can block against its input, like 
+   * sending/receiving UDP packets. It shouldn't be used by audio. For that, use the
+   * readSlotNonBlocking.   
+   * \param ptrToReadSlot Pointer to read slot from the RingBuffer
+   */
+  void readSlotBlocking(int8_t* ptrToReadSlot);
+  
+  /** \brief Same as insertSlotBlocking but non-blocking (asynchronous)
+   * \param ptrToSlot Pointer to slot to insert into the RingBuffer
+   */
+  void insertSlotNonBlocking(const int8_t* ptrToSlot);
+  
+  /** \brief Same as readSlotBlocking but non-blocking (asynchronous)
+   * \param ptrToReadSlot Pointer to read slot from the RingBuffer
+   */
+  void readSlotNonBlocking(int8_t* ptrToReadSlot);
+
+
+protected:
+
+  /** \brief Sets the memory in the Read Slot when uderrun occurs. By default,
+   * this sets it to 0. Override this method in a subclass for a different behavior.
+   * \param ptrToReadSlot Pointer to read slot from the RingBuffer
+   */
+  virtual void setUnderrunReadSlot(int8_t* ptrToReadSlot);
+
+  /** \brief Uses the last read slot to set the memory in the Read Slot.
+   * 
+   * The last read slot is the last packet that arrived, so if no new packets are received, 
+   * it keeps looping the same packet.
+   * \param ptrToReadSlot Pointer to read slot from the RingBuffer
+   */
+  virtual void setMemoryInReadSlotWithLastReadSlot(int8_t* ptrToReadSlot);
+
+private:
+
+  /// \brief Resets the ring buffer for reads under-runs non-blocking
+  void underrunReset();
+  /// \brief Resets the ring buffer for writes over-flows non-blocking
+  void overflowReset();
+  /// \brief Helper method to debug, prints member variables to terminal
+  void debugDump() const;
+
+  const int mSlotSize; ///< The size of one slot in byes
+  const int mNumSlots; ///< Number of Slots
+  const int mTotalSize; ///< Total size of the mRingBuffer = mSlotSize*mNumSlotss
+  int mReadPosition; ///< Read Positions in the RingBuffer (Tail)
+  int mWritePosition; ///< Write Position in the RingBuffer (Head)
+  int mFullSlots; ///< Number of used (full) slots, in slot-size
+  int8_t* mRingBuffer; ///< 8-bit array of data (1-byte)
+  int8_t* mLastReadSlot; ///< Last slot read  
+
+  // Thread Synchronization Private Members
+  QMutex mMutex; ///< Mutex to protect read and write operations
+  QWaitCondition mBufferIsNotFull; ///< Buffer not full condition to monitor threads
+  QWaitCondition mBufferIsNotEmpty; ///< Buffer not empty condition to monitor threads
+};
+
+#endif
diff --git a/src/RingBufferWavetable.h b/src/RingBufferWavetable.h
new file mode 100644 (file)
index 0000000..e63dedf
--- /dev/null
@@ -0,0 +1,71 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file RingBufferWavetable.h
+ * \author Juan-Pablo Caceres
+ * \date September 2008
+ */
+
+#ifndef __RINGBUFFERWAVETABLE_H__
+#define __RINGBUFFERWAVETABLE_H__
+
+
+/** \brief Same as RingBuffer, except that it uses the Wavetable mode for
+ * lost or late packets.
+ */
+class RingBufferWavetable : public RingBuffer
+{
+public:
+  /** \brief The class constructor
+   * \param SlotSize Size of one slot in bytes
+   * \param NumSlots Number of slots
+   */
+  RingBufferWavetable(int SlotSize, int NumSlots) : RingBuffer(SlotSize, NumSlots) {}
+
+  /** \brief The class destructor
+   */
+  virtual ~RingBufferWavetable() {}
+
+protected:
+  /** \brief Sets the memory in the Read Slot when uderrun occurs. This loops as a 
+   * wavetable in the last received packet.
+   * \param ptrToReadSlot Pointer to read slot from the RingBuffer
+   */
+  virtual void setUnderrunReadSlot(int8_t* ptrToReadSlot)
+  {
+    setMemoryInReadSlotWithLastReadSlot(ptrToReadSlot);
+  }
+
+};
+
+
+#endif //__RINGBUFFERWAVETABLE_H__
diff --git a/src/Settings.cpp b/src/Settings.cpp
new file mode 100644 (file)
index 0000000..5b764da
--- /dev/null
@@ -0,0 +1,376 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file Settings.cpp
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+#include "Settings.h"
+#include "LoopBack.h"
+#include "NetKS.h"
+#include "UdpMasterListener.h"
+#include "JackTripWorker.h"
+#include "jacktrip_globals.h"
+
+#include <iostream>
+#include <getopt.h> // for command line parsing
+#include <cstdlib>
+
+#include "ThreadPoolTest.h"
+
+using std::cout; using std::endl;
+
+int gVerboseFlag = 0;
+
+
+//*******************************************************************************
+Settings::Settings() :
+  mJackTrip(NULL),
+  mJackTripMode(JackTrip::SERVER),
+  mDataProtocol(JackTrip::UDP),
+  mNumChans(2),
+  mBufferQueueLength(gDefaultQueueLength),
+  mAudioBitResolution(JackAudioInterface::BIT16),
+  mPortNum(gDefaultPort),
+  mClientName(NULL),
+  mUnderrrunZero(false),
+  mLoopBack(false),
+  mJamLink(false),
+  mEmptyHeader(false),
+  mJackTripServer(false),
+  mRedundancy(1)
+{}
+
+//*******************************************************************************
+Settings::~Settings()
+{
+  stopJackTrip();
+  delete mJackTrip;
+}
+
+//*******************************************************************************
+void Settings::parseInput(int argc, char** argv)
+{
+  // If no command arguments are given, print instructions
+  if(argc == 1) {
+    printUsage();
+    std::exit(0);
+  }
+
+  // Usage example at:
+  // http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Option-Example.html#Getopt-Long-Option-Example
+  // options descriptor
+  //----------------------------------------------------------------------------
+  static struct option longopts[] = {
+    // These options set a flag, has to be sepcified as a long option --verbose
+    { "verbose", no_argument, &gVerboseFlag, 1 },
+    // These options don't set a flag.
+    { "numchannels", required_argument, NULL, 'n' }, // Number of input and output channels
+    { "server", no_argument, NULL, 's' }, // Run in server mode
+    { "client", required_argument, NULL, 'c' }, // Run in client mode, set server IP address
+    { "jacktripserver", no_argument, NULL, 'S' }, // Run in JamLink mode
+    { "pingtoserver", required_argument, NULL, 'C' }, // Run in ping to server mode, set server IP address
+    { "portoffset", required_argument, NULL, 'o' }, // Port Offset from 4464
+    { "queue", required_argument, NULL, 'q' }, // Queue Length
+    { "redundancy", required_argument, NULL, 'r' }, // Redundancy
+    { "bitres", required_argument, NULL, 'b' }, // Audio Bit Resolution
+    { "zerounderrun", no_argument, NULL, 'z' }, // Use Underrun to Zeros Mode
+    { "loopback", no_argument, NULL, 'l' }, // Run in loopback mode
+    { "jamlink", no_argument, NULL, 'j' }, // Run in JamLink mode
+    { "emptyheader", no_argument, NULL, 'e' }, // Run in JamLink mode
+    { "clientname", required_argument, NULL, 'J' }, // Run in JamLink mode
+    { "version", no_argument, NULL, 'v' }, // Version Number
+    { "help", no_argument, NULL, 'h' }, // Print Help
+    { NULL, 0, NULL, 0 }
+  };
+
+  // Parse Command Line Arguments
+  //----------------------------------------------------------------------------
+  /// \todo Specify mandatory arguments
+  int ch;
+  while ( (ch = getopt_long(argc, argv, "n:sc:SC:o:q:r:b:zljeJ:vh", longopts, NULL)) != -1 )
+    switch (ch) {
+      
+    case 'n': // Number of input and output channels
+      //-------------------------------------------------------
+      mNumChans = atoi(optarg);
+      break;
+    case 's': // Run in server mode
+      //-------------------------------------------------------
+      mJackTripMode = JackTrip::SERVER;
+      break;
+    case 'S': // Run in jacktripserver mode
+      //-------------------------------------------------------
+      mJackTripServer = true;
+      break;
+    case 'c': // Client mode
+      //-------------------------------------------------------
+      mJackTripMode = JackTrip::CLIENT;
+      mPeerAddress = optarg;
+      break;
+    case 'C': // Ping to server
+      //-------------------------------------------------------
+      mJackTripMode = JackTrip::CLIENTTOPINGSERVER;
+      mPeerAddress = optarg;
+      break;
+    case 'o': // Port Offset
+      //-------------------------------------------------------
+      mPortNum += atoi(optarg);
+      break;
+    case 'b':
+      //-------------------------------------------------------
+      if      ( atoi(optarg) == 8 ) {
+       mAudioBitResolution = JackAudioInterface::BIT8; }
+      else if ( atoi(optarg) == 16 ) {
+       mAudioBitResolution = JackAudioInterface::BIT16; }
+      else if ( atoi(optarg) == 24 ) {
+       mAudioBitResolution = JackAudioInterface::BIT24; }
+      else if ( atoi(optarg) == 32 ) {
+       mAudioBitResolution = JackAudioInterface::BIT32; }
+      else {
+       std::cerr << "--bitres ERROR: Wrong bit resolutions: " 
+                 << atoi(optarg) << " is not supported." << endl;
+       printUsage();
+       std::exit(1); }
+      break;
+    case 'q':
+      //-------------------------------------------------------
+      if ( atoi(optarg) <= 0 ) {
+       std::cerr << "--queue ERROR: The queue has to be a positive integer" << endl;
+       printUsage();
+       std::exit(1); }
+      else {
+       mBufferQueueLength = atoi(optarg);
+      }
+      break;
+    case 'r':
+      //-------------------------------------------------------
+      if ( atoi(optarg) <= 0 ) {
+       std::cerr << "--queue ERROR: The queue has to be a positive integer" << endl;
+       printUsage();
+       std::exit(1); }
+      else {
+       mRedundancy = atoi(optarg);
+      }
+      break;
+    case 'z': // underrun to zero
+      //-------------------------------------------------------
+      mUnderrrunZero = true;
+      break;
+    case 'l': // loopback
+      //-------------------------------------------------------
+      mLoopBack = true;
+      break;
+    case 'e': // jamlink
+      //-------------------------------------------------------
+      mEmptyHeader = true;
+      break;
+    case 'j': // jamlink
+      //-------------------------------------------------------
+      mJamLink = true;
+      break;
+    case 'J':
+      //-------------------------------------------------------
+      mClientName = optarg;
+      break;
+    case 'v':
+      //-------------------------------------------------------
+      cout << "JackTrip VERSION: " << gVersion << endl;
+      cout << "Copyright (c) 2008-2009 Juan-Pablo Caceres, Chris Chafe." << endl;
+      cout << "SoundWIRE group at CCRMA, Stanford University" << endl;
+      cout << "" << endl;
+      std::exit(0);
+      break;
+    case 'h':
+      //-------------------------------------------------------
+      printUsage();
+      std::exit(0);
+      break;
+    default:
+      //-------------------------------------------------------
+      printUsage();
+      std::exit(0);
+      break;
+    }
+
+  // Warn user if undefined options where entered
+  //----------------------------------------------------------------------------
+  if (optind < argc) {
+    cout << gPrintSeparator << endl;
+    cout << "WARINING: The following entered options have no effect" << endl;
+    cout << "          They will be ignored!" << endl;
+    cout << "          Type jacktrip to see options." << endl;
+    for( ; optind < argc; optind++) {
+      printf("argument: %s\n", argv[optind]);
+    }
+    cout << gPrintSeparator << endl;
+  }
+}
+
+
+//*******************************************************************************
+void Settings::printUsage()
+{
+  cout << "" << endl;
+  cout << "JackTrip: A System for High-Quality Audio Network Performance" << endl;
+  cout << "over the Internet" << endl;
+  cout << "Copyright (c) 2008-2009 Juan-Pablo Caceres, Chris Chafe." << endl;
+  cout << "SoundWIRE group at CCRMA, Stanford University" << endl;
+  cout << "VERSION: " << gVersion << endl;
+  cout << "-----------------------------------------------------------------------------" << endl;
+  cout << "" << endl;
+  cout << "Usage: jacktrip [-s|-c host] [options]" << endl;
+  cout << "" << endl;
+  cout << "Options: " << endl;
+  cout << " -s, --server                             Run in Server Mode" << endl;
+  cout << " -c, --client      <peer_host_IP_number>  Run in Client Mode" << endl;
+  cout << " -n, --numchannels #                      Number of Input and Output Channels (default "
+       << 2 << ")" << endl;
+  cout << " -q, --queue       # (1 or more)          Queue Buffer Length, in Packet Size (default " 
+       << gDefaultQueueLength << ")" << endl;
+  cout << " -r, --redundancy  # (1 or more)          Packet Redundancy to avoid glitches with packet losses (defaul 1)" 
+       << endl;
+  cout << " -o, --portoffset  #                      Receiving port offset from base port " << gDefaultPort << endl;
+  cout << " -b, --bitres      # (8, 16, 24, 32)      Audio Bit Rate Resolutions (default 16)" << endl;
+  cout << " -z, --zerounderrun                       Set buffer to zeros when underrun occurs (defaults to wavetable)" << endl;
+  cout << " -l, --loopback                           Run in Loop-Back Mode" << endl;
+  cout << " -j, --jamlink                            Run in JamLink Mode (Connect to a JamLink Box)" << endl;
+  cout << " --clientname                             Change default client name (default is JackTrip)" << endl;
+  cout << " -v, --version                            Prints Version Number" << endl;
+  cout << " -h, --help                               Prints this Help" << endl;
+  cout << "" << endl;
+}
+
+
+//*******************************************************************************
+void Settings::startJackTrip()
+{
+
+  ///\todo Change this, just here to test
+  if ( mJackTripServer ) {
+    UdpMasterListener* udpmaster = new UdpMasterListener;
+    udpmaster->start();
+    
+    //---Thread Pool Test--------------------------------------------
+    /*
+    cout << "BEFORE START" << endl;
+    ThreadPoolTest* thtest = new ThreadPoolTest();
+    // QThreadPool takes ownership and deletes 'hello' automatically
+    QThreadPool::globalInstance()->start(thtest);
+
+    cout << "AFTER START" << endl;
+    sleep(2);
+    thtest->stop();
+    QThreadPool::globalInstance()->waitForDone();
+    */
+    //---------------------------------------------------------------
+  }
+  
+  else {
+    
+    //JackTrip jacktrip(mJackTripMode, mDataProtocol, mNumChans,
+    //     mBufferQueueLength, mAudioBitResolution);
+    mJackTrip = new JackTrip(mJackTripMode, mDataProtocol, mNumChans,
+                            mBufferQueueLength, mRedundancy, mAudioBitResolution);
+    
+    // Change client name if different from default
+    if (mClientName != NULL) {
+      mJackTrip->setClientName(mClientName);
+    }
+
+    // Set buffers to zero when underrun
+    if ( mUnderrrunZero ) {
+      cout << "Setting buffers to zero when underrun..." << endl;
+      cout << gPrintSeparator << std::endl;
+      mJackTrip->setUnderRunMode(JackTrip::ZEROS);
+    }
+    
+    // Set peer address in server mode
+    if ( mJackTripMode == JackTrip::CLIENT || mJackTripMode == JackTrip::CLIENTTOPINGSERVER ) {
+      mJackTrip->setPeerAddress(mPeerAddress.toLatin1().data()); }
+    
+    // Set Ports
+    cout << "SETTING ALL PORTS" << endl;
+    mJackTrip->setAllPorts(mPortNum);
+
+    // Set in JamLink Mode
+    if ( mJamLink ) {
+      cout << "Running in JamLink Mode..." << endl;
+      cout << gPrintSeparator << std::endl;
+      mJackTrip->setPacketHeaderType(DataProtocol::JAMLINK);
+    }
+
+    // Set in EmptyHeader Mode
+    if ( mEmptyHeader ) {
+      cout << "Running in EmptyHeader Mode..." << endl;
+      cout << gPrintSeparator << std::endl;
+      mJackTrip->setPacketHeaderType(DataProtocol::EMPTY);
+    }
+
+    // Add Plugins
+    if ( mLoopBack ) {
+      cout << "Running in Loop-Back Mode..." << endl;
+      cout << gPrintSeparator << std::endl;
+      //std::tr1::shared_ptr<LoopBack> loopback(new LoopBack(mNumChans));
+      //mJackTrip->appendProcessPlugin(loopback.get());
+
+      LoopBack* loopback = new LoopBack(mNumChans);
+      mJackTrip->appendProcessPlugin(loopback);
+
+      // ----- Test Karplus Strong -----------------------------------
+      //std::tr1::shared_ptr<NetKS> loopback(new NetKS());
+      //mJackTrip->appendProcessPlugin(loopback);
+      //loopback->play();
+      //NetKS* netks = new NetKS;
+      //mJackTrip->appendProcessPlugin(netks);
+      //netks->play();
+      // -------------------------------------------------------------
+    }
+    
+    // Start JackTrip
+    mJackTrip->start();
+    
+    /* 
+       sleep(10);
+       cout << "Stoping JackTrip..." << endl;
+       mJackTrip->stop();
+    */
+  }
+}
+
+
+//*******************************************************************************
+void Settings::stopJackTrip()
+{
+  mJackTrip->stop();
+}
diff --git a/src/Settings.h b/src/Settings.h
new file mode 100644 (file)
index 0000000..5c08808
--- /dev/null
@@ -0,0 +1,84 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file Settings.h
+ * \author Juan-Pablo Caceres
+ * \date July 2008
+ */
+
+
+#ifndef __SETTINGS_H__
+#define __SETTINGS_H__
+
+#include "DataProtocol.h"
+#include "JackAudioInterface.h"
+#include "JackTrip.h"
+
+/** \brief Class to set usage options and parse settings from input
+ */
+class Settings
+{
+public:
+  Settings();
+  virtual ~Settings();
+
+  /// \brief Parses command line input
+  void parseInput(int argc, char** argv);
+
+  void startJackTrip();
+  void stopJackTrip();
+
+  /// \brief Prints usage help
+  void printUsage();
+
+  bool getLoopBack() { return mLoopBack; };
+
+private:
+  JackTrip* mJackTrip; ///< JackTrip class
+  JackTrip::jacktripModeT mJackTripMode; ///< JackTrip::jacktripModeT
+  JackTrip::dataProtocolT mDataProtocol; ///< Data Protocol
+  int mNumChans; ///< Number of Channels (inputs = outputs)
+  int mBufferQueueLength; ///< Audio Buffer from network queue length
+  JackAudioInterface::audioBitResolutionT mAudioBitResolution;
+  QString mPeerAddress; ///< Peer Address to use in jacktripModeT::CLIENT Mode
+  int mPortNum; ///< Port Number
+  char* mClientName;
+  bool mUnderrrunZero; ///< Use Underrun to Zero mode
+
+  bool mLoopBack; ///< Loop-back mode
+  bool mJamLink; ///< JamLink mode
+  bool mEmptyHeader; ///< EmptyHeader mode
+  bool mJackTripServer; ///< JackTrip Server mode
+  unsigned int mRedundancy; ///< Redundancy factor for data in the network
+};
+
+#endif
diff --git a/src/TestRingBuffer.h b/src/TestRingBuffer.h
new file mode 100644 (file)
index 0000000..136710b
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __TESTRINGBUFFER__
+#define __TESTRINGBUFFER__
+
+#include "RingBuffer.h"
+#include <QThread>
+#include <iostream>
+
+static RingBuffer rb(2,100);
+
+class TestRingBufferWrite : public QThread
+{
+public:
+  
+  void run()
+  {
+    int8_t* writeSlot;
+    writeSlot = new int8_t[2];
+    writeSlot[0] = *"a";
+    writeSlot[1] = *"b";    
+    while (true) {
+      //std::cout << "writing BEFORE" << std::endl;
+      rb.insertSlotBlocking(writeSlot);
+      //std::cout << "writing AFTER" << std::endl;
+    }
+  }
+
+};
+
+
+class TestRingBufferRead : public QThread
+{
+public:
+  
+  void run()
+  {
+    int8_t* readSlot;
+    readSlot = new int8_t[2];
+    while (true) {
+      //std::cout << "reading BEFORE" << std::endl;
+      rb.readSlotBlocking(readSlot);
+      //std::cout << "reading AFTER" << std::endl;
+      //std::cout << *(readSlot) << std::endl;
+      //std::cout << *(readSlot+1) << std::endl;
+    }
+  }
+};
+
+#endif
+
diff --git a/src/ThreadPoolTest.h b/src/ThreadPoolTest.h
new file mode 100644 (file)
index 0000000..1c85653
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * \file ThreadPoolTest.h
+ * \author Juan-Pablo Caceres
+ * \date October 2008
+ */
+
+#ifndef __THREADPOOLTEST_H__
+#define __THREADPOOLTEST_H__
+
+#include <QThreadPool>
+#include <QEventLoop>
+#include <QThread>
+#include <QObject>
+
+#include <iostream>
+
+#include "NetKS.h"
+#include "JackTripWorkerMessages.h"
+
+
+class ThreadPoolTest : public QObject, public QRunnable
+//class ThreadPoolTest : public QThread
+{
+  Q_OBJECT;
+  
+public:
+  ThreadPoolTest()
+  {
+    setAutoDelete(false);
+  }
+
+  void run()
+  {
+    JackTripWorkerMessages jtm;
+    QThread testThread;
+    //jtm.moveToThread(&testThread);
+
+    //QObject::connect(&jtm, SIGNAL(signalTest()), &jtm, SLOT(slotTest()), Qt::QueuedConnection);
+    testThread.start();
+    jtm.play();
+    //testThread.wait();
+    
+    //std::cout << "--------------- BEFORE ---------------" << std::endl;
+    //NetKS netks;
+    //netks.play();
+    //std::cout << "--------------- AFTER ---------------" << std::endl;
+    
+    QEventLoop loop;
+    //QObject::connect(this, SIGNAL(stopELoop()), &loop, SLOT(quit()), Qt::QueuedConnection);
+    loop.exec();
+    //std::cout << "--------------- EXITING QRUNNABLE---------------" << std::endl;
+    /*
+    while (true) {
+      std::cout << "Hello world from thread" << std::endl;
+      sleep(1);
+    }
+    */
+  }
+
+  void stop()
+  {
+    std::cout << "--------------- ELOOP STOP---------------" << std::endl;
+    emit stopELoop();
+  }
+
+signals:
+  void stopELoop();
+
+private slots:
+  void fromServer()
+  {
+    std::cout << "--------------- SIGNAL RECEIVED ---------------" << std::endl;
+  }
+
+};
+
+#endif //__THREADPOOLTEST_H__
diff --git a/src/UdpDataProtocol.cpp b/src/UdpDataProtocol.cpp
new file mode 100644 (file)
index 0000000..9e2275f
--- /dev/null
@@ -0,0 +1,505 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file UdpDataProtocol.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#include "UdpDataProtocol.h"
+#include "jacktrip_globals.h"
+#include "JackTrip.h"
+
+#include <cstring>
+#include <iostream>
+#include <cstdlib>
+#include <cerrno>
+#include <stdexcept>
+#include <sys/socket.h> // for POSIX Sockets
+
+using std::cout; using std::endl;
+
+// NOTE: It's better not to use
+// using namespace std;
+// because some functions (like exit()) get confused with QT functions
+
+// sJackMutex definition
+QMutex UdpDataProtocol::sUdpMutex;
+
+//*******************************************************************************
+UdpDataProtocol::UdpDataProtocol(JackTrip* jacktrip, const runModeT runmode,
+                                 int bind_port, int peer_port,
+                                 unsigned int udp_redundancy_factor) :
+DataProtocol(jacktrip, runmode, bind_port, peer_port),
+mBindPort(bind_port), mPeerPort(peer_port),
+mRunMode(runmode),
+mAudioPacket(NULL), mFullPacket(NULL),
+mUdpRedundancyFactor(udp_redundancy_factor)
+{
+  if (mRunMode == RECEIVER) {
+    QObject::connect(this, SIGNAL(signalWatingTooLong(int)),
+                     jacktrip, SLOT(slotUdpWatingTooLong(int)), Qt::QueuedConnection);
+  }
+}
+
+
+//*******************************************************************************
+UdpDataProtocol::~UdpDataProtocol()
+{
+  delete[] mAudioPacket;
+  delete[] mFullPacket;
+  wait();
+} 
+
+
+//*******************************************************************************
+void UdpDataProtocol::setPeerAddress(const char* peerHostOrIP)
+{
+  mPeerAddress.setAddress(peerHostOrIP);
+  // check if the ip address is valid
+  if ( mPeerAddress.isNull() ) {
+    std::cerr << "ERROR: Incorrect presentation format address" << endl;
+    std::cerr << "'" << peerHostOrIP <<"' does not seem to be a valid IP address" << endl;
+    throw std::invalid_argument("");
+  }
+  /*
+  else {
+    std::cout << "Peer Address set to: "
+        << mPeerAddress.toString().toStdString() << std::endl;
+    cout << gPrintSeparator << endl;
+    usleep(100);
+  }
+  */
+}
+
+
+//*******************************************************************************
+void UdpDataProtocol::bindSocket(QUdpSocket& UdpSocket)
+{
+  QMutexLocker locker(&sUdpMutex);
+
+  // Creat socket descriptor
+  int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+  // Set local IPv4 Address
+  struct sockaddr_in local_addr;
+  ::bzero(&local_addr, sizeof(local_addr));
+  local_addr.sin_family = AF_INET; //AF_INET: IPv4 Protocol
+  local_addr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY: let the kernel decide the active address
+  local_addr.sin_port = htons(mBindPort); //set local port
+
+  // Set socket to be reusable, this is platform dependent
+  int one = 1;
+#if defined ( __LINUX__ )
+  ::setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+#endif
+#if defined ( __MAC_OSX__ )
+  // This option is not avialable on Linux, and without it MAC OS X
+  // has problems rebinding a socket
+  ::setsockopt(sock_fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+#endif
+
+  // Bind the Socket
+  if ( (::bind(sock_fd, (struct sockaddr *) &local_addr, sizeof(local_addr))) < 0 )
+  { throw std::runtime_error("ERROR: UDP Socket Bind Error"); }
+
+  // To be able to use the two UDP sockets bound to the same port number,
+  // we connect the receiver and issue a SHUT_WR.
+  if (mRunMode == SENDER) {
+    // We use the sender as an unconnected UDP socket
+    UdpSocket.setSocketDescriptor(sock_fd, QUdpSocket::BoundState,
+                                  QUdpSocket::WriteOnly);
+  }
+  else if (mRunMode == RECEIVER) {
+    // Set peer IPv4 Address
+    struct sockaddr_in peer_addr;
+    bzero(&peer_addr, sizeof(peer_addr));
+    peer_addr.sin_family = AF_INET; //AF_INET: IPv4 Protocol
+    peer_addr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY: let the kernel decide the active address
+    peer_addr.sin_port = htons(mPeerPort); //set local port
+    // Connect the socket and issue a Write shutdown (to make it a
+    // reader socket only)
+    if ( (::inet_pton(AF_INET, mPeerAddress.toString().toLatin1().constData(),
+                      &peer_addr.sin_addr)) < 1 )
+    { throw std::runtime_error("ERROR: Invalid address presentation format"); }
+    if ( (::connect(sock_fd, (struct sockaddr *) &peer_addr, sizeof(peer_addr))) < 0)
+    { throw std::runtime_error("ERROR: Could not connect UDP socket"); }
+    if ( (::shutdown(sock_fd,SHUT_WR)) < 0)
+    { throw std::runtime_error("ERROR: Could suntdown SHUT_WR UDP socket"); }
+
+    UdpSocket.setSocketDescriptor(sock_fd, QUdpSocket::ConnectedState,
+                                  QUdpSocket::ReadOnly);
+    cout << "UDP Socket Receiving in Port: " << mBindPort << endl;
+    cout << gPrintSeparator << endl;
+  }
+
+  // OLD CODE WITHOUT POSIX FIX--------------------------------------------------
+  /*
+  /// \todo if port is already used, try binding in a different port
+  QUdpSocket::BindMode bind_mode;
+  if (mRunMode == RECEIVER) {
+    bind_mode = QUdpSocket::DontShareAddress; }
+  else if (mRunMode == SENDER) { //Share sender socket
+    bind_mode = QUdpSocket::ShareAddress; }
+
+  // QHostAddress::Any : let the kernel decide the active address
+  if ( !UdpSocket.bind(QHostAddress::Any, mBindPort, bind_mode) ) {
+    throw std::runtime_error("Could not bind UDP socket. It may be already binded.");
+  }
+  else {
+    if ( mRunMode == RECEIVER ) {
+      cout << "UDP Socket Receiving in Port: " << mBindPort << endl;
+      cout << gPrintSeparator << endl;
+    }
+  }
+  */
+  // ----------------------------------------------------------------------------
+}
+
+
+//*******************************************************************************
+int UdpDataProtocol::receivePacket(QUdpSocket& UdpSocket, char* buf, const size_t n)
+{
+  // Block until There's something to read
+  while ( (UdpSocket.pendingDatagramSize() < n) && !mStopped ) { QThread::usleep(100); }
+  int n_bytes = UdpSocket.readDatagram(buf, n);
+  return n_bytes;
+}
+
+
+//*******************************************************************************
+int UdpDataProtocol::sendPacket(QUdpSocket& UdpSocket, const QHostAddress& PeerAddress,
+                                const char* buf, const size_t n)
+{
+  int n_bytes = UdpSocket.writeDatagram(buf, n, PeerAddress, mPeerPort);
+  return n_bytes;
+}
+
+
+//*******************************************************************************
+void UdpDataProtocol::getPeerAddressFromFirstPacket(QUdpSocket& UdpSocket,
+                                                    QHostAddress& peerHostAddress,
+                                                    uint16_t& port)
+{
+  while ( !UdpSocket.hasPendingDatagrams() ) {
+    msleep(100);
+  }
+  char buf[1];
+  UdpSocket.readDatagram(buf, 1, &peerHostAddress, &port);
+}
+
+
+//*******************************************************************************
+void UdpDataProtocol::run()
+{
+  mStopped = false;
+  
+  // Creat and bind sockets
+  QUdpSocket UdpSocket;
+  bindSocket(UdpSocket); // Bind Socket
+  QHostAddress PeerAddress;
+  PeerAddress = mPeerAddress;
+
+  // Setup Audio Packet buffer 
+  size_t audio_packet_size = getAudioPacketSizeInBites();
+  //cout << "audio_packet_size: " << audio_packet_size << endl;
+  mAudioPacket = new int8_t[audio_packet_size];
+  std::memset(mAudioPacket, 0, audio_packet_size); // set buffer to 0
+  
+  // Setup Full Packet buffer
+  int full_packet_size = mJackTrip->getPacketSizeInBytes();
+  //cout << "full_packet_size: " << full_packet_size << endl;
+  mFullPacket = new int8_t[full_packet_size];
+  std::memset(mFullPacket, 0, full_packet_size); // set buffer to 0
+
+  bool timeout = false; // Time out flag for packets that arrive too late
+  
+  // Put header in first packet
+  mJackTrip->putHeaderInPacket(mFullPacket, mAudioPacket);
+
+  // Redundancy Variables
+  // (Algorithm explained at the end of this file)
+  // ---------------------------------------------
+  int full_redundant_packet_size = full_packet_size * mUdpRedundancyFactor;
+  int8_t* full_redundant_packet;
+  full_redundant_packet = new int8_t[full_redundant_packet_size];
+  std::memset(full_redundant_packet, 0, full_redundant_packet_size); // Initialize to 0
+
+  // Set realtime priority (function in jacktrip_globals.h)
+  set_crossplatform_realtime_priority();
+
+  // Connect signals and slots for packets arriving too late notifications
+  QObject::connect(this, SIGNAL(signalWatingTooLong(int)),
+                   this, SLOT(printUdpWaitedTooLong(int)),
+                   Qt::QueuedConnection);
+
+  switch ( mRunMode )
+  {
+  case RECEIVER : {
+      //----------------------------------------------------------------------------------- 
+      // Wait for the first packet to be ready and obtain address
+      // from that packet
+      std::cout << "Waiting for Peer..." << std::endl;
+      // This blocks waiting for the first packet
+      while ( !UdpSocket.hasPendingDatagrams() ) { QThread::msleep(100); }
+      int first_packet_size = UdpSocket.pendingDatagramSize();
+      // The following line is the same as
+      // int8_t* first_packet = new int8_t[first_packet_size];
+      // but avoids memory leaks
+      std::tr1::shared_ptr<int8_t> first_packet(new int8_t[first_packet_size]);
+      receivePacket( UdpSocket, reinterpret_cast<char*>(first_packet.get()), first_packet_size);
+      // Check that peer has the same audio settings
+      mJackTrip->checkPeerSettings(first_packet.get());
+      mJackTrip->parseAudioPacket(mFullPacket, mAudioPacket);
+      std::cout << "Received Connection for Peer!" << std::endl;
+
+      // Redundancy Variables
+      // --------------------
+      // NOTE: These types need to be the same unsigned integer as the sequence
+      // number in the header. That way, they wrap around in the "same place"
+      uint16_t current_seq_num = 0; // Store current sequence number
+      uint16_t last_seq_num = 0;    // Store last package sequence number
+      uint16_t newer_seq_num = 0;   // Store newer sequence number
+
+      while ( !mStopped )
+      {
+        // Timer to report packets arriving too late
+        // This QT method gave me a lot of trouble, so I replaced it with my own 'waitForReady'
+        // that uses signals and slots and can also report with packets have not
+        // arrive for a longer time
+        //timeout = UdpSocket.waitForReadyRead(30);
+        timeout = waitForReady(UdpSocket, 60000); //60 seconds
+
+        // OLD CODE WITHOUT REDUNDANCY----------------------------------------------------
+        /*
+        // This is blocking until we get a packet...
+        receivePacket( UdpSocket, reinterpret_cast<char*>(mFullPacket), full_packet_size);
+
+        mJackTrip->parseAudioPacket(mFullPacket, mAudioPacket);
+
+        // ...so we want to send the packet to the buffer as soon as we get in from
+        // the socket, i.e., non-blocking
+        //mRingBuffer->insertSlotNonBlocking(mAudioPacket);
+        mJackTrip->writeAudioBuffer(mAudioPacket);
+        */
+        //----------------------------------------------------------------------------------
+        receivePacketRedundancy(UdpSocket,
+                               full_redundant_packet,
+                               full_redundant_packet_size,
+                               full_packet_size,
+                               current_seq_num,
+                               last_seq_num,
+                               newer_seq_num);
+      }
+      break; }
+
+  case SENDER : {
+      //----------------------------------------------------------------------------------- 
+      while ( !mStopped )
+      {
+        // OLD CODE WITHOUT REDUNDANCY -----------------------------------------------------
+        /*
+        // We block until there's stuff available to read
+        mJackTrip->readAudioBuffer( mAudioPacket );
+        mJackTrip->putHeaderInPacket(mFullPacket, mAudioPacket);
+        // This will send the packet immediately
+        //int bytes_sent = sendPacket( reinterpret_cast<char*>(mFullPacket), full_packet_size);
+        sendPacket( UdpSocket, PeerAddress, reinterpret_cast<char*>(mFullPacket), full_packet_size);
+        */
+        //----------------------------------------------------------------------------------
+        sendPacketRedundancy(UdpSocket,
+                             PeerAddress,
+                             full_redundant_packet,
+                             full_redundant_packet_size,
+                             full_packet_size);
+      }
+      break; }
+  }
+}
+
+
+//*******************************************************************************
+bool UdpDataProtocol::waitForReady(QUdpSocket& UdpSocket, int timeout_msec)
+{
+  int loop_resolution_usec = 100; // usecs to wait on each loop
+  int emit_resolution_usec = 10000; // 10 milliseconds
+  int timeout_usec = timeout_msec * 1000;
+  int ellaped_time_usec = 0; // Ellapsed time in milliseconds
+
+  while ( ( !(UdpSocket.hasPendingDatagrams()) && (ellaped_time_usec <= timeout_usec) )
+    && !mStopped ){
+    //cout << mStopped << endl;
+    QThread::usleep(loop_resolution_usec);
+    ellaped_time_usec += loop_resolution_usec;
+    
+    if ( !(ellaped_time_usec % emit_resolution_usec) ) {
+      emit signalWatingTooLong(static_cast<int>(ellaped_time_usec/1000));
+    }
+  }
+  
+  if ( ellaped_time_usec >= timeout_usec )
+  {
+    emit signalWatingTooLong(ellaped_time_usec/1000);
+    return false;
+  }
+  return true;
+}
+
+
+//*******************************************************************************
+void UdpDataProtocol::printUdpWaitedTooLong(int wait_msec)
+{
+  int wait_time = 30; // msec
+  if ( !(wait_msec%wait_time) ) {
+    std::cerr << "UDP is waited too long (more than " << wait_time << "ms)..." << endl;
+  }
+}
+
+
+//*******************************************************************************
+void UdpDataProtocol::receivePacketRedundancy(QUdpSocket& UdpSocket,
+                                              int8_t* full_redundant_packet,
+                                              int full_redundant_packet_size,
+                                              int full_packet_size,
+                                              uint16_t& current_seq_num,
+                                              uint16_t& last_seq_num,
+                                              uint16_t& newer_seq_num)
+{
+  // This is blocking until we get a packet...
+  receivePacket( UdpSocket, reinterpret_cast<char*>(full_redundant_packet),
+                 full_redundant_packet_size);
+
+  // Get Packet Sequence Number
+  newer_seq_num =
+      mJackTrip->getPeerSequenceNumber(full_redundant_packet);
+  current_seq_num = newer_seq_num;
+
+
+  //cout << current_seq_num << " ";
+  int redun_last_index = 0;
+  for (unsigned int i = 1; i<mUdpRedundancyFactor; i++) {
+    // Check if the package we receive is the next one expected, i.e.,
+    // current_seq_num == (last_seq_num+1)
+    if ( (current_seq_num == (last_seq_num+1))) { break; }
+
+    // if it's not, check the next one until it is the corresponding packet
+    // or there aren't more available packets
+    redun_last_index = i; // index of packet to use in the redundant packet
+    current_seq_num =
+        mJackTrip->getPeerSequenceNumber( full_redundant_packet + (i*full_packet_size) );
+    //cout << current_seq_num << " ";
+  }
+  //cout << endl;
+
+  last_seq_num = newer_seq_num; // Save last read packet
+
+  // Send to audio all available audio packets, in order
+  for (int i = redun_last_index; i>=0; i--) {
+    memcpy(mFullPacket,
+           full_redundant_packet + (i*full_packet_size),
+           full_packet_size);
+    mJackTrip->parseAudioPacket(mFullPacket, mAudioPacket);
+    mJackTrip->writeAudioBuffer(mAudioPacket);
+  }
+}
+
+//*******************************************************************************
+void UdpDataProtocol::sendPacketRedundancy(QUdpSocket& UdpSocket,
+                                           QHostAddress& PeerAddress,
+                                           int8_t* full_redundant_packet,
+                                           int full_redundant_packet_size,
+                                           int full_packet_size)
+{
+  mJackTrip->readAudioBuffer( mAudioPacket );
+  mJackTrip->putHeaderInPacket(mFullPacket, mAudioPacket);
+
+  // Move older packets to end of array of redundant packets
+  std::memmove(full_redundant_packet+full_packet_size,
+               full_redundant_packet,
+               full_packet_size*(mUdpRedundancyFactor-1));
+  // Copy new packet to the begining of array
+  std::memcpy(full_redundant_packet,
+              mFullPacket, full_packet_size);
+
+  // 10% (or other number) packet lost simulation.
+  // Uncomment the if to activate
+  //---------------------------------------------------------------------------------
+  //int random_integer = rand();
+  //if ( random_integer > (RAND_MAX/10) )
+  //{
+  sendPacket( UdpSocket, PeerAddress, reinterpret_cast<char*>(full_redundant_packet),
+              full_redundant_packet_size);
+  //}
+  //---------------------------------------------------------------------------------
+
+  mJackTrip->increaseSequenceNumber();
+}
+
+
+/*
+  The Redundancy Algorythmn works as follows. We send a packet that contains
+  a mUdpRedundancyFactor number of packets (header+audio). This big packet looks 
+  as follows
+  
+  ----------  ------------       -----------------------------------
+  | UDP[n] |  | UDP[n-1] |  ...  | UDP[n-(mUdpRedundancyFactor-1)] | 
+  ----------  ------------       -----------------------------------
+
+  Then, for the new audio buffer, we shift everything to the right and send:
+  
+  ----------  ------------       -------------------------------------
+  | UDP[n+1] |  | UDP[n] |  ...  | UDP[n-(mUdpRedundancyFactor-1)+1] | 
+  ----------  ------------       -------------------------------------
+
+  etc...
+
+  For a redundancy factor of 4, this will look as follows:
+  ----------  ----------  ----------  ----------
+  | UDP[4] |  | UDP[3] |  | UDP[2] |  | UDP[1] |
+  ----------  ----------  ----------  ----------
+  
+  ----------  ----------  ----------  ----------
+  | UDP[5] |  | UDP[4] |  | UDP[3] |  | UDP[2] |
+  ----------  ----------  ----------  ----------
+
+  ----------  ----------  ----------  ----------
+  | UDP[6] |  | UDP[5] |  | UDP[4] |  | UDP[3] |
+  ----------  ----------  ----------  ----------
+
+  etc...
+
+  Then, the receiving end checks if the firs packet in the list is the one it should use,
+  otherwise it continure reding the mUdpRedundancyFactor packets until it finds the one that
+  should come next (this can better perfected by just jumping until the correct packet).
+  If it has more than one packet that it hasn't yet received, it sends it to the soundcard
+  one by one.
+*/
diff --git a/src/UdpDataProtocol.h b/src/UdpDataProtocol.h
new file mode 100644 (file)
index 0000000..fbce562
--- /dev/null
@@ -0,0 +1,197 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file UdpDataProtocol.h
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#ifndef __UDPDATAPROTOCOL_H__
+#define __UDPDATAPROTOCOL_H__
+
+#include <QThread>
+#include <QUdpSocket>
+#include <QHostAddress>
+
+#include "DataProtocol.h"
+#include "jacktrip_types.h"
+#include "jacktrip_globals.h"
+
+/** \brief UDP implementation of DataProtocol class
+ *
+ * The class has a <tt>bind port</tt> and a <tt>peer port</tt>. The meaning of these
+ * depends on the runModeT. If it's a SENDER, <tt>bind port</tt> is the source port and
+ * <tt>peer port</tt> is the destination port for each UDP packet. If it's a RECEIVER,
+ * the <tt>bind port</tt> destination port (for incoming packets) and the <tt>peer port</tt>
+ * is the source port.
+ *
+ * The SENDER and RECEIVER socket can share the same port/address pair (for compatibility
+ * with the JamLink boxes). This is achieved setting
+ * the resusable property in the socket for address and port. You have to
+ * externaly check if the port is already binded if you want to avoid re-binding to the
+ * same port.
+ */
+class UdpDataProtocol : public DataProtocol
+{
+  Q_OBJECT;
+  
+public:
+  
+  /** \brief The class constructor 
+   * \param jacktrip Pointer to the JackTrip class that connects all classes (mediator)
+   * \param runmode Sets the run mode, use either SENDER or RECEIVER
+   * \param bind_port Port number to bind for this socket (this is the receive or send port depending on the runmode)
+   * \param peer_port Peer port number (this is the receive or send port depending on the runmode)
+   * \param udp_redundancy_factor Number of redundant packets
+   */
+  UdpDataProtocol(JackTrip* jacktrip, const runModeT runmode,
+      int bind_port, int peer_port,
+                 unsigned int udp_redundancy_factor = 1);
+  
+  /** \brief The class destructor
+   */
+  virtual ~UdpDataProtocol();  
+
+  /** \brief Set the Peer address to connect to
+   * \param peerHostOrIP IPv4 number or host name
+   */
+  void setPeerAddress(const char* peerHostOrIP);
+
+  /** \brief Receives a packet. It blocks until a packet is received
+   *
+   * This function makes sure we recieve a complete packet
+   * of size n
+   * \param buf Buffer to store the recieved packet
+   * \param n size of packet to receive
+   * \return number of bytes read, -1 on error
+   */
+  //virtual int receivePacket(char* buf, const size_t n);
+  virtual int receivePacket(QUdpSocket& UdpSocket, char* buf, const size_t n);
+  
+  /** \brief Sends a packet
+   *
+   * This function meakes sure we send a complete packet
+   * of size n
+   * \param buf Buffer to send
+   * \param n size of packet to receive
+   * \return number of bytes read, -1 on error
+   */
+  virtual int sendPacket(QUdpSocket& UdpSocket, const QHostAddress& PeerAddress,
+                        const char* buf, const size_t n);
+  
+  /** \brief Obtains the peer address from the first UDP packet received. This address
+   * is used by the SERVER mode to connect back to the client.
+   * \param peerHostAddress QHostAddress to store the peer address
+   * \param port Receiving port
+   */
+  virtual void getPeerAddressFromFirstPacket(QUdpSocket& UdpSocket,
+                                            QHostAddress& peerHostAddress,
+               uint16_t& port);
+
+  /** \brief Sets the bind port number
+    */
+  void setBindPort(int port)
+  { mBindPort = port; }
+
+  /** \brief Sets the peer port number
+    */
+  void setPeerPort(int port)
+  { mPeerPort = port; }
+
+  /** \brief Implements the Thread Loop. To start the thread, call start()
+   * ( DO NOT CALL run() )
+   *
+   * This function creats and binds all the socket and start the connection loop thread.
+   */
+  virtual void run();
+
+
+private slots:
+  void printUdpWaitedTooLong(int wait_msec);
+
+
+signals:
+
+  /// \brief Signals when waiting every 10 milliseconds, with the total wait on wait_msec
+  /// \param wait_msec Total wait in milliseconds
+  void signalWatingTooLong(int wait_msec);
+
+
+private:
+
+  /** \brief Binds the UDP socket to the available address and specified port
+   */
+  void bindSocket(QUdpSocket& UdpSocket);
+  /** \brief This function blocks until data is available for reading in the 
+   * QUdpSocket. The function will timeout after timeout_msec microseconds.
+   *
+   * This function is intended to replace QAbstractSocket::waitForReadyRead which has
+   * some problems with multithreading.
+   *
+   * \return returns true if there is data available for reading;
+   * otherwise it returns false (if an error occurred or the operation timed out)
+   */
+  bool waitForReady(QUdpSocket& UdpSocket, int timeout_msec);
+
+  /** \brief Redundancy algorythm at the receiving end
+    */
+  void receivePacketRedundancy(QUdpSocket& UdpSocket,
+                               int8_t* full_redundant_packet,
+                               int full_redundant_packet_size,
+                               int full_packet_size,
+                               uint16_t& current_seq_num,
+                               uint16_t& last_seq_num,
+                               uint16_t& newer_seq_num);
+
+  /** \brief Redundancy algorythm at the sender  end
+    */
+  void sendPacketRedundancy(QUdpSocket& UdpSocket,
+                            QHostAddress& PeerAddress,
+                            int8_t* full_redundant_packet,
+                            int full_redundant_packet_size,
+                            int full_packet_size);
+
+  int mBindPort; ///< Local Port number to Bind
+  int mPeerPort; ///< Peer Port number
+  const runModeT mRunMode; ///< Run mode, either SENDER or RECEIVER
+
+  QHostAddress mPeerAddress; ///< The Peer Address
+
+  int8_t* mAudioPacket; ///< Buffer to store Audio Packets
+  int8_t* mFullPacket; ///< Buffer to store Full Packet (audio+header)
+
+  unsigned int mUdpRedundancyFactor; ///< Factor of redundancy
+  static QMutex sUdpMutex; ///< Mutex to make thread safe the binding process
+};
+
+#endif // __UDPDATAPROTOCOL_H__
diff --git a/src/UdpDataProtocolPOSIX.cpp.tmp b/src/UdpDataProtocolPOSIX.cpp.tmp
new file mode 100644 (file)
index 0000000..fe77daa
--- /dev/null
@@ -0,0 +1,145 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file UdpDataProtocol.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#include "UdpDataProtocol.h"
+
+#include <cstring>
+#include <iostream>
+#include <cstdlib>
+#include <cerrno>
+
+// NOTE: It's better not to use
+// using namespace std;
+// because some functions (like exit()) get confused with QT functions
+
+
+
+//*******************************************************************************
+UdpDataProtocol::UdpDataProtocol(const runModeT runmode, const char* peerHostOrIP)
+  : DataProtocol(runmode)
+{
+  setPeerIPv4Address(peerHostOrIP);
+  setBindSocket();
+}
+
+
+//*******************************************************************************
+void UdpDataProtocol::setBindSocket()
+{
+  // UDP socket creation
+  mSockFd = socket(AF_INET, SOCK_DGRAM, 0);
+  if ( mSockFd < 0 ) {
+    std::cerr << "ERROR: UDP Socket Error" << std::endl;
+    std::exit(0);      
+  }
+  
+  // Bind local address and port
+  /// \todo Bind to a different port in case this one is used by a different instance 
+  /// of the program
+  struct sockaddr_in LocalIPv4Addr = getLocalIPv4AddressStruct();
+  int nBind = bind(mSockFd, (struct sockaddr *) &LocalIPv4Addr, sizeof(LocalIPv4Addr));
+  if ( nBind < 0 ) {
+    std::cerr << "ERROR: UDP Socket Bind Error" << std::endl;
+    std::exit(0);
+  }
+  
+  std::cout << "Successful socket creation and port binding" << std::endl;
+  
+  //Connected UDP
+  struct sockaddr_in PeerIPv4Addr = getPeerIPv4AddressStruct();
+  int nCon = ::connect(mSockFd, (struct sockaddr *) &PeerIPv4Addr, sizeof(PeerIPv4Addr));
+  if ( nCon < 0) {
+    std::cerr << "ERROR: UDP Socket Connect Error" << std::endl;
+    std::exit(0);
+  }
+}
+
+
+//*******************************************************************************
+// Adapted form Stevens' "Unix Network Programming", third edition
+// Page 88 (readn)
+size_t UdpDataProtocol::receivePacket(char* buff, size_t n)
+{
+  size_t nleft;
+  ssize_t nread;
+  char* ptr;
+  
+  ptr = buff;
+  nleft = n;
+  while (nleft > 0) {
+    if ( (nread = ::read(mSockFd, ptr, nleft)) < 0) {
+      if (errno == EINTR)
+       nread = 0; // and call read() again
+      else
+       return(-1);
+    } else if (nread == 0)
+      break; // EOF
+    
+    nleft -= nread;
+    ptr   += nread;
+  }
+  return(n - nleft);
+}
+
+
+
+//*******************************************************************************
+// Adapted form Stevens' "Unix Network Programming", third edition
+// Page 88 (writen)
+// Write "n" bytes to a descriptor
+size_t UdpDataProtocol::sendPacket(const char* buff, size_t n)
+{
+  size_t nleft;
+  ssize_t nwritten;
+  const char* ptr;
+  
+  ptr = buff;
+  nleft = n;
+  while (nleft > 0) {
+    if ( (nwritten = ::write(mSockFd, ptr, nleft)) <= 0) {
+      if (nwritten < 0 && errno == EINTR)
+       nwritten = 0; // and call write() again
+      else
+       return(-1); // error
+    }
+    
+    nleft -= nwritten;
+    ptr   += nwritten;
+  }
+  return(n);
+}
+
diff --git a/src/UdpDataProtocolPOSIX.h.tmp b/src/UdpDataProtocolPOSIX.h.tmp
new file mode 100644 (file)
index 0000000..a7fb087
--- /dev/null
@@ -0,0 +1,92 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file UdpDataProtocol.h
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#ifndef __UDPDATAPROTOCOL_H__
+#define __UDPDATAROTOCOL_H__
+
+#include "DataProtocol.h"
+
+/** \brief UDP implementation of DataProtocol class
+ * 
+ * 
+ *
+ */
+class UdpDataProtocol : public DataProtocol
+{
+public:
+
+  /** \brief The class constructor 
+   * \param runmode Sets the run mode, use either SENDER or RECEIVER
+   * \param peerHostOrIP IPv4 number or host name
+   */
+  UdpDataProtocol(const runModeT runmode, const char* peerHostOrIP);
+
+  /** \brief The class destructor
+   */
+  virtual ~UdpDataProtocol() {};
+
+  /** \brief Receives a packet
+   *
+   * This function makes sure we recieve a complete packet
+   * of size n
+   * \param buf Buffer to store the recieved packet
+   * \param n size of packet to receive
+   * \return number of bytes read, -1 on error
+   */
+  virtual size_t receivePacket(char* buf, size_t n);
+
+  /** \brief Sends a packet
+   *
+   * This function meakes sure we send a complete packet
+   * of size n
+   * \param buff Buffer to send
+   * \param n size of packet to receive
+   * \return number of bytes read, -1 on error
+   */
+  virtual size_t sendPacket(const char* buff, size_t n);
+
+  //virtual void run();
+
+
+private:
+
+  void setBindSocket();
+
+  int mSockFd; ///< Socket file descriptor 
+};
+
+#endif
diff --git a/src/UdpMasterListener.cpp b/src/UdpMasterListener.cpp
new file mode 100644 (file)
index 0000000..874eda4
--- /dev/null
@@ -0,0 +1,186 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file UdpMasterListener.cpp
+ * \author Juan-Pablo Caceres and Chris Chafe
+ * \date September 2008
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+
+#include "UdpMasterListener.h"
+#include "JackTripWorker.h"
+#include "jacktrip_globals.h"
+
+using std::cout; using std::endl;
+
+
+//*******************************************************************************
+UdpMasterListener::UdpMasterListener(int server_port) :
+    mJTWorker(NULL),
+    mServerPort(server_port),
+    mStopped(false),
+    mTotalRunningThreads(0)
+{
+  // Register JackTripWorker with the master listener
+  mJTWorker = new JackTripWorker(this);
+  mThreadPool.setExpiryTimeout(3000); // msec (-1) = forever
+  // Inizialize IP addresses
+  for (int i = 0; i<gMaxThreads; i++) { 
+    mActiveAddress[i][0] = 0; // 32-bit ints
+    mActiveAddress[i][1] = 0; // 32-bit ints
+  }
+  // Set the base dynamic port
+  // The Dynamic and/or Private Ports are those from 49152 through 65535
+  mBasePort = ( random() % ( (65535 - gMaxThreads) - 49152 ) ) + 49152;
+}
+
+
+//*******************************************************************************
+UdpMasterListener::~UdpMasterListener()
+{
+  mThreadPool.waitForDone ();
+  delete mJTWorker;
+}
+
+
+//*******************************************************************************
+void UdpMasterListener::run()
+{
+  mStopped = false;
+
+  // Create objects on the stack
+  QUdpSocket MasterUdpSocket;
+  QHostAddress PeerAddress;
+  uint16_t peer_port; // Ougoing Peer port, in case they're not using the default
+
+  // Bind the socket to the well known port
+  bindUdpSocket(MasterUdpSocket, mServerPort);
+
+  char buf[1];
+  cout << "Server Listening in UDP Port: " << mServerPort << endl;
+  cout << "Waiting for client..." << endl;
+  cout << "=======================================================" << endl;
+  while ( !mStopped )
+    {
+      //cout << "WAITING........................." << endl;
+      while ( MasterUdpSocket.hasPendingDatagrams() ) 
+       {
+         //cout << "Received request from Client!" << endl;
+         // Get Client IP Address and outgoing port from packet
+         int rv = MasterUdpSocket.readDatagram(buf, 1, &PeerAddress, &peer_port);
+         //cout << "Peer Port in Server ==== " << peer_port << endl;
+         if (rv < 0) { std::cerr << "ERROR: Bad UDP packet read..." << endl; }
+
+         /// \todo Get number of channels in the client from header
+
+         // check by comparing 32-bit addresses
+         /// \todo Add the port number in the comparison
+         int id = isNewAddress(PeerAddress.toIPv4Address(), peer_port);
+
+         //cout << "IDIDIDIDIDDID === " << id << endl;
+
+         // If the address is new, create a new thread in the pool
+         if (id >= 0) // old address is -1
+           {
+             // redirect port and spawn listener
+             sendToPoolPrototype(id);
+             // wait until one is complete before another spawns
+             while (mJTWorker->isSpawning()) { QThread::msleep(1); }
+             mTotalRunningThreads++;
+             cout << "Total Running Threads:  " << mTotalRunningThreads << endl;
+             cout << "=======================================================" << endl;
+           }
+         //cout << "ENDDDDDDDDDDDDDDDDDd === " << id << endl;
+       }
+      QThread::msleep(100);
+    }
+}
+
+
+//*******************************************************************************
+void UdpMasterListener::sendToPoolPrototype(int id)
+{
+  cout << "id ID **********@@@@@@@@@@@@@@@@@@@@@************** " << id <<  endl;
+  mJTWorker->setJackTrip(id, mActiveAddress[id][0],
+                        mBasePort+(2*id), mActiveAddress[id][1],
+                        1); /// \todo temp default to 1 channel
+  mThreadPool.start(mJTWorker, QThread::TimeCriticalPriority); //send one thread to the pool
+}
+
+
+//*******************************************************************************
+void UdpMasterListener::bindUdpSocket(QUdpSocket& udpsocket, int port)
+{
+  // QHostAddress::Any : let the kernel decide the active address
+  if ( !udpsocket.bind(QHostAddress::Any,
+                       port, QUdpSocket::DefaultForPlatform) ) {
+    //std::cerr << "ERROR: could not bind UDP socket" << endl;
+    //std::exit(1);
+    throw std::runtime_error("Could not bind UDP socket. It may be already binded.");
+  }
+  else {
+    cout << "UDP Socket Receiving in Port: " << port << endl;
+  }
+}
+
+
+//*******************************************************************************
+// check by comparing 32-bit addresses
+int UdpMasterListener::isNewAddress(uint32_t address, uint16_t port)
+{
+  /// \todo Add the port number in the comparison, i.e., compart IP/port pair
+  
+  bool busyAddress = false;
+  int id = 0;
+  while ( !busyAddress && (id<mThreadPool.activeThreadCount()) )
+    {
+      if ( address==mActiveAddress[id][0] &&  port==mActiveAddress[id][1]) { busyAddress = true; }
+      id++;
+    }      
+  if ( !busyAddress ) { 
+    mActiveAddress[id][0] = address;
+    mActiveAddress[id][1] = port;
+  }
+  return ((busyAddress) ? -1 : id);
+}
+
+
+//*******************************************************************************
+int UdpMasterListener::releasePort(int id)
+{ 
+  mActiveAddress[id][0] = 0;
+  mActiveAddress[id][1] = 0;
+  return 0; /// \todo Check if we really need to return an argument here
+}
diff --git a/src/UdpMasterListener.h b/src/UdpMasterListener.h
new file mode 100644 (file)
index 0000000..338229e
--- /dev/null
@@ -0,0 +1,123 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file UdpMasterListener.h
+ * \author Juan-Pablo Caceres and Chris Chafe
+ * \date September 2008
+ */
+
+#ifndef __UDPMASTERLISTENER_H__
+#define __UDPMASTERLISTENER_H__
+
+#include <iostream>
+
+#include <QThread>
+#include <QThreadPool>
+#include <QUdpSocket>
+#include <QHostAddress>
+
+#include "jacktrip_types.h"
+#include "jacktrip_globals.h"
+class JackTripWorker; // forward declaration
+
+
+/** \brief Master UDP listener on the Server.
+ *
+ * This creates a server that will listen on the well know port (the server port) and will 
+ * spawn JackTrip threads into the Thread pool. Clients request a connection.
+ */
+class UdpMasterListener : public QThread
+{
+  Q_OBJECT;
+
+public:
+  UdpMasterListener(int server_port = gServerUdpPort);
+  virtual ~UdpMasterListener();
+  
+  /** \brief Implements the Thread Loop. To start the thread, call start()
+   * ( DO NOT CALL run() )
+   */
+  void run();
+
+  /// \brief Stops the execution of the Thread
+  void stop() { mStopped = true; };
+
+  int releasePort(int id);
+
+private slots:
+  void testRecieve()
+  {
+    std::cout << "========= TEST RECEIVE SLOT ===========" << std::endl;
+  }
+
+signals:
+  void Listening();
+  void ClientAddressSet();
+
+
+private:
+  /** \brief Binds a QUdpSocket. It chooses the available (active) interface.
+   * \param udpsocket a QUdpSocket
+   * \param port Port number
+   */
+  static void bindUdpSocket(QUdpSocket& udpsocket, int port);
+
+  /* \brief Send the JackTripWorker to the thread pool. This will run
+   * until it's done. We still have control over the prototype class.
+   * \param id Identification Number
+   */
+  void sendToPoolPrototype(int id);
+
+  /** \brief Check if address is already handled, if not add to array
+   * \param IPv4 address as a number
+   * \return -1 if address is busy, id number if not
+   */ 
+  int isNewAddress(uint32_t address, uint16_t port);
+
+  QUdpSocket mUdpMasterSocket; ///< The UDP socket
+  QHostAddress mPeerAddress; ///< The Peer Address
+
+  JackTripWorker* mJTWorker; ///< Class that will be used as prototype
+  QThreadPool mThreadPool; ///< The Thread Pool
+
+  int mServerPort; //< Server known port number
+  int mBasePort;
+  uint32_t mActiveAddress[gMaxThreads][2]; ///< Active addresses pool numbers (32 bits IPv4 numbers)
+  QHash<uint32_t, uint16_t> mActiveAddresPortPair;
+
+  /// Boolean stop the execution of the thread
+  volatile bool mStopped;
+  int mTotalRunningThreads; ///< Number of Threads running in the pool
+};
+
+
+#endif //__UDPMASTERLISTENER_H__
diff --git a/src/build b/src/build
new file mode 100755 (executable)
index 0000000..546567d
--- /dev/null
+++ b/src/build
@@ -0,0 +1,25 @@
+#!/bin/bash
+## Created by Juan-Pablo Caceres
+
+# Check for Platform
+platform='unknown'
+unamestr=`uname`
+if [[ "$unamestr" == 'Linux' ]]; then
+    echo "Building on Linux"
+    platform='linux'
+elif [[ "$unamestr" == 'Darwin' ]]; then
+    echo "Building on Mac OS X"
+    platform='macosx'
+fi
+
+# Set qmake command name
+if [[ $platform == 'linux' ]]; then
+    QCMD=qmake-qt4
+elif [[ $platform == 'macosx' ]]; then
+    QCMD=qmake
+fi
+
+# Build
+$QCMD jacktrip.pro
+make clean
+make release
diff --git a/src/jacktrip-1.0.5.diff b/src/jacktrip-1.0.5.diff
new file mode 100644 (file)
index 0000000..30292b9
--- /dev/null
@@ -0,0 +1,26 @@
+Index: src/JackTripWorker.h
+===================================================================
+--- src/JackTripWorker.h       (revision 495)
++++ src/JackTripWorker.h       (working copy)
+@@ -46,6 +46,8 @@
+ #include <QHostAddress>
+ #include <QMutex>
++#include "jacktrip_types.h"
++
+ class JackTrip; // forward declaration
+ class UdpMasterListener; // forward declaration
+Index: src/jacktrip_globals.cpp
+===================================================================
+--- src/jacktrip_globals.cpp   (revision 495)
++++ src/jacktrip_globals.cpp   (working copy)
+@@ -38,6 +38,8 @@
+ #include "jacktrip_globals.h"
+ #include "jacktrip_types.h"
++#include <stdio.h>
++
+ #if defined ( __LINUX__ )
+ #include <sched.h>
+ #endif //__LINUX__
diff --git a/src/jacktrip.pro b/src/jacktrip.pro
new file mode 100644 (file)
index 0000000..b92e69d
--- /dev/null
@@ -0,0 +1,68 @@
+#******************************
+# Created by Juan-Pablo Caceres
+#******************************
+
+CONFIG += qt thread debug_and_release build_all
+CONFIG(debug, debug|release) {
+  TARGET = jacktrip_debug
+  } else {
+  TARGET = jacktrip
+  }
+QT -= gui
+QT += network
+INCLUDEPATH+=/usr/local/include
+LIBS += -ljack -lm
+macx {
+  message(MAC OS X)
+  CONFIG -= app_bundle
+  CONFIG += x86 #ppc
+  LIBS += -framework CoreAudio
+  DEFINES += __MAC_OSX__
+  }
+linux-g++ {
+  message(Linux)
+  QMAKE_CXXFLAGS += -g -O2
+  DEFINES += __LINUX__
+  }
+DESTDIR = .
+QMAKE_CLEAN += ./jacktrip ./jacktrip_debug
+target.path = /usr/bin
+INSTALLS += target
+
+# Input
+HEADERS += DataProtocol.h \
+           JackAudioInterface.h \
+           JackTrip.h \
+           jacktrip_globals.h \
+           jacktrip_types.h \
+           JackTripThread.h \
+           JackTripWorker.h \
+           JackTripWorkerMessages.h \
+           LoopBack.h \
+           NetKS.h \
+           PacketHeader.h \
+           ProcessPlugin.h \
+           RingBuffer.h \
+           RingBufferWavetable.h \
+           Settings.h \
+           TestRingBuffer.h \
+           ThreadPoolTest.h \
+           UdpDataProtocol.h \
+           UdpMasterListener.h \
+           jacktrip_tests.cpp
+SOURCES += DataProtocol.cpp \
+           JackAudioInterface.cpp \
+           JackTrip.cpp \
+           jacktrip_globals.cpp \
+           jacktrip_main.cpp \
+           jacktrip_tests.cpp \
+           JackTripThread.cpp \
+           JackTripWorker.cpp \
+           LoopBack.cpp \
+           PacketHeader.cpp \
+           ProcessPlugin.cpp \
+           RingBuffer.cpp \
+           Settings.cpp \
+           tests.cpp \
+           UdpDataProtocol.cpp \
+           UdpMasterListener.cpp
diff --git a/src/jacktrip_globals.cpp b/src/jacktrip_globals.cpp
new file mode 100644 (file)
index 0000000..df5c24d
--- /dev/null
@@ -0,0 +1,196 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file globals.cpp
+ * \author Juan-Pablo Caceres
+ * \date August 2008
+ */
+
+#include "jacktrip_globals.h"
+#include "jacktrip_types.h"
+
+#include <stdio.h>
+
+#if defined ( __LINUX__ )
+#include <sched.h>
+#endif //__LINUX__
+
+#if defined ( __MAC_OSX__ )
+#include <mach/mach.h>
+#include <mach/thread_policy.h>
+
+//#include <mach/processor.h>
+
+//#include <mach/clock.h>
+//#include <sys/kernel.h>
+//#include <mach/kern/clock.h>
+
+//#include <Kernel/kern/clock.h>
+//#include <kern/kern_types.h>
+//m#include <kern/kern_types.h>
+//#include <Kernel/kern/clock.h>
+//#include <kern/clock.h>
+
+
+//#include <assert.h>
+//#include <CoreServices/CoreServices.h>
+//#include <mach/mach.h>
+//#include <mach/mach_time.h>
+//#include <unistd.h>
+
+
+
+
+//#include <mach/machine.h>
+//#include <mach/mach_time.h>
+//#include <mach/thread_call.h>
+//#include <mach/processor.h>
+//#include <mach/macro_help.h>
+
+#endif //__MAC_OSX__
+
+
+#if defined ( __MAC_OSX__ )
+//*******************************************************************************
+//http://developer.apple.com/DOCUMENTATION/Darwin/Conceptual/KernelProgramming/scheduler/chapter_8_section_4.html
+//http://lists.apple.com/archives/darwin-dev/2007/Sep/msg00035.html
+int set_realtime(int period, int computation, int constraint)
+{
+  //AbsoluteTime time;
+  //clock_get_uptime((uint64_t *)&time);
+
+  //uint64_t result;
+  //clock_get_uptime(&result);
+  //clock_get_system_microtime(&result,&result);
+
+  struct thread_time_constraint_policy ttcpolicy;
+  int ret;
+  
+  ttcpolicy.period=period; // HZ/160
+  ttcpolicy.computation=computation; // HZ/3300;
+  ttcpolicy.constraint=constraint; // HZ/2200;
+  ttcpolicy.preemptible=1;
+  
+  if ((ret=thread_policy_set(mach_thread_self(),
+                            THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&ttcpolicy,
+                            THREAD_TIME_CONSTRAINT_POLICY_COUNT)) != KERN_SUCCESS) {
+    fprintf(stderr, "set_realtime() failed.\n");
+    return 0;
+  }
+  return 1;
+}
+#endif //__MAC_OSX__ 
+
+
+#if defined ( __LINUX__ )
+//*******************************************************************************
+int get_fifo_priority (bool half)
+{
+  int min, max, priority;
+  min = sched_get_priority_min (SCHED_FIFO);
+  max = sched_get_priority_max (SCHED_FIFO);
+  if (half) {
+    priority = (max  - (max - min) / 2); }
+  else {
+    priority = max; }
+
+  //priority=min;
+  return priority;
+}
+#endif //__LINUX__
+
+
+#if defined ( __LINUX__ )
+//*******************************************************************************
+int set_fifo_priority (bool half)
+{
+  struct sched_param p;
+  int priority;
+  //  scheduling priority
+
+
+  if (true) // (!getuid () || !geteuid ())
+    {
+      priority = get_fifo_priority (half);
+      p.sched_priority = priority;
+
+      if (sched_setscheduler (0, SCHED_FIFO, &p) == -1)
+       {
+         fprintf (stderr,
+                  "\ncould not activate scheduling with priority %d\n",
+                  priority);
+         return -1;
+       }
+      seteuid (getuid ());
+      //fprintf (stderr,
+      //       "\nset scheduling priority to %d (SCHED_FIFO)\n",
+      //       priority);
+    }
+  else
+    {
+      fprintf (stderr,
+              "\ninsufficient privileges to set scheduling priority\n");
+      priority = 0;
+    }
+  return priority;
+}
+#endif //__LINUX__
+
+
+#if defined ( __LINUX__ )
+//*******************************************************************************
+int set_realtime_priority (void)
+{
+  struct sched_param schp;
+
+  memset (&schp, 0, sizeof (schp));
+  schp.sched_priority = sched_get_priority_max (SCHED_FIFO);
+  if (sched_setscheduler (0, SCHED_FIFO, &schp) != 0)
+    {
+      perror ("set_scheduler");
+      return -1;
+    }
+  return 0;
+}
+#endif //__LINUX__
+
+void set_crossplatform_realtime_priority()
+{
+#if defined ( __LINUX__ )
+  set_fifo_priority (false);
+#endif //__LINUX__
+#if defined ( __MAC_OSX__ )
+  set_realtime(1250000,60000,90000);
+#endif //__MAC_OSX__
+}
+
+
diff --git a/src/jacktrip_globals.h b/src/jacktrip_globals.h
new file mode 100644 (file)
index 0000000..f9d2d76
--- /dev/null
@@ -0,0 +1,126 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file globals.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#ifndef __JACKTRIP_GLOBALS_H__
+#define __JACKTRIP_GLOBALS_H__
+
+#include "JackAudioInterface.h"
+
+
+//namespace JackTrip/// \todo Add this namespace
+
+const char* const gVersion = "1.0.5"; ///< JackTrip version
+
+//*******************************************************************************
+/// \name Default Values
+//@{
+const int gDefaultNumInChannels = 2;
+const int gDefaultNumOutChannels = 2;
+const JackAudioInterface::audioBitResolutionT gDefaultBitResolutionMode = 
+  JackAudioInterface::BIT16;
+const int gDefaultQueueLength = 4;
+const int gDefaultOutputQueueLength = 4;
+//@}
+
+
+//*******************************************************************************
+/// \name Network related ports
+//@{
+const int gDefaultPort = 4464; ///< Default JackTrip Port
+//const int gInputPort_0 = 4464; ///< Input base port
+//const int gOutputPort_0 = 4465; ///< Output base port
+//const int gDefaultSendPort = 4464; ///< Default for to use to send packet
+//@}
+
+
+//*******************************************************************************
+/// \name Separator for terminal printing
+//@{
+const char* const gPrintSeparator = "---------------------------------------------------------";
+//@}
+
+
+//*******************************************************************************
+/// \name Global flags
+//@{
+extern int gVerboseFlag; ///< Verbose mode flag declaration
+//@}
+
+
+//*******************************************************************************
+/// \name JackAudio
+//@{
+const int gJackBitResolution = 32; ///< Audio Bit Resolution of the Jack Server
+//@}
+
+
+//*******************************************************************************
+/// \name Global Functions
+
+void set_crossplatform_realtime_priority();
+
+//@{
+// Linux Specific Functions
+#if defined ( __LINUX__ )
+/// \brief Returns fifo priority
+int get_fifo_priority (bool half);
+/// \brief Set fifo priority (if user has sufficient privileges).
+int set_fifo_priority (bool half);
+int set_realtime_priority (void);
+#endif //__LINUX__
+//@}
+
+//@{
+// Mac OS X Specific Functions
+#if defined ( __MAC_OSX__ )
+int set_realtime(int period, int computation, int constraint);
+#endif //__MAC_OSX__ 
+//@}
+  
+
+//*******************************************************************************
+/// \name JackTrip Server parameters
+//@{
+/// Maximum Threads that can be run at the same time
+const int gMaxThreads = 290; // some pthread limit around 297?
+
+/// Public well-known UDP port to where the clients will connect
+const int gServerUdpPort = 4464;
+//@}
+
+
+#endif
diff --git a/src/jacktrip_main.cpp b/src/jacktrip_main.cpp
new file mode 100644 (file)
index 0000000..e0d4203
--- /dev/null
@@ -0,0 +1,86 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file main.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+#include <iostream>
+
+#include <QCoreApplication>
+
+#include "JackAudioInterface.h"
+#include "UdpDataProtocol.h"
+#include "RingBuffer.h"
+#include "JackTrip.h"
+#include "Settings.h"
+//#include "TestRingBuffer.h"
+#include "LoopBack.h"
+#include "PacketHeader.h"
+#include "JackTripThread.h"
+#include "jacktrip_tests.cpp"
+
+#include "jacktrip_globals.h"
+
+using std::cout; using std::endl;
+
+
+int main(int argc, char** argv)
+{
+  QCoreApplication app(argc, argv);
+
+  //--------TESTS--------------------------
+  //main_tests(argc, argv); // test functions
+  //while (true) sleep(9999);
+  //---------------------------------------
+
+  // Get Settings from user
+  // ----------------------
+  try 
+    {
+      // Get Settings from user
+      // ----------------------
+      Settings* settings = new Settings;
+      settings->parseInput(argc, argv);
+      settings->startJackTrip();
+    }
+  catch ( const std::exception & e )
+    {
+      std::cerr << "ERROR:" << endl;
+      std::cerr << e.what() << endl;
+      std::cerr << "Exiting JackTrip..." << endl;
+      std::cerr << gPrintSeparator << endl;
+      return -1;
+    }
+  return app.exec();
+}
diff --git a/src/jacktrip_tests.cpp b/src/jacktrip_tests.cpp
new file mode 100644 (file)
index 0000000..17cddf1
--- /dev/null
@@ -0,0 +1,103 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file jacktrip_tests.cpp
+ * \author Juan-Pablo Caceres
+ * \date September 2008
+ */
+
+#include <iostream>
+
+#include <QVector>
+
+#include "JackTripThread.h"
+
+using std::cout; using std::endl;
+
+const int num_jacktrips = 5;
+const int base_port = 4464;
+
+
+void main_tests(int argc, char** argv);
+void test_threads_server();
+void test_threads_client(const char* peer_address);
+
+
+void main_tests(int /*argc*/, char** argv)
+{
+  if (argv[1][0] == 's' )
+    {
+      test_threads_server();
+    }
+  else if (argv[1][0] == 'c' )
+    { 
+      test_threads_client("171.64.197.209");
+    }
+}
+
+
+// Test many servers running at the same time
+void test_threads_server()
+{
+  QVector<JackTripThread*> jacktrips;
+  jacktrips.resize(num_jacktrips);
+  int port_num;
+  for (int i = 0; i < num_jacktrips; i++)
+    {
+      port_num = base_port + i*10;
+      cout << "Port Number: " << port_num << endl;
+      jacktrips[i] = new JackTripThread(JackTrip::SERVER);
+      jacktrips[i]->setPort(port_num);
+      jacktrips[i]->start(QThread::NormalPriority);
+      //sleep(1);
+    }
+}
+
+
+// Test many servers running at the same time
+void test_threads_client(const char* peer_address)
+{
+  QVector<JackTripThread*> jacktrips;
+  jacktrips.resize(num_jacktrips);
+  int port_num;
+  for (int i = 0; i < num_jacktrips; i++)
+    {
+      port_num = base_port + i*10;
+      cout << "Port Number: " << port_num << endl;
+      jacktrips[i] = new JackTripThread(JackTrip::CLIENT);
+      jacktrips[i]->setPort(port_num);
+      jacktrips[i]->setPeerAddress(peer_address);
+      //sleep(1);
+      jacktrips[i]->start(QThread::NormalPriority);
+      //sleep(1);
+    }
+}
diff --git a/src/jacktrip_types.h b/src/jacktrip_types.h
new file mode 100644 (file)
index 0000000..08bfe87
--- /dev/null
@@ -0,0 +1,85 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file jacktrip_types_jacktrip.h
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+
+
+#ifndef __JACKTRIP_TYPES_H__
+#define __JACKTRIP_TYPES_H__
+
+#include <jack/types.h>
+#include <QtGlobal> //For QT4 types
+
+//-------------------------------------------------------------------------------
+/** \name Audio typedefs
+ *
+ */
+//-------------------------------------------------------------------------------
+//@{
+/// Audio sample type
+typedef jack_default_audio_sample_t sample_t; 
+//@}
+
+
+//-------------------------------------------------------------------------------
+/** \name Typedefs that guaranty some specific bit length
+ *
+ * It uses the QT4 types. This can be changed in the future, keeping
+ * compatibility for the rest of the code.
+ */
+//-------------------------------------------------------------------------------
+//@{
+/// Typedef for <tt>unsigned char</tt>. This type is guaranteed to be 8-bit.
+typedef quint8 uint8_t;
+/// Typedef for <tt>unsigned short</tt>. This type is guaranteed to be 16-bit.
+typedef quint16 uint16_t;
+/// Typedef for <tt>unsigned int</tt>. This type is guaranteed to be 32-bit.
+typedef quint32 uint32_t;
+/// \brief Typedef for <tt>unsigned long long int</tt>. This type is guaranteed to 
+/// be 64-bit.
+//typedef quint64 uint64_t;
+/// Typedef for <tt>signed char</tt>. This type is guaranteed to be 8-bit.
+typedef qint8 int8_t;
+/// Typedef for <tt>signed short</tt>. This type is guaranteed to be 16-bit.
+typedef qint16 int16_t;
+/// Typedef for <tt>signed int</tt>. This type is guaranteed to be 32-bit.
+typedef qint32 int32_t;
+/// \brief Typedef for <tt>long long int</tt>. This type is guaranteed to 
+/// be 64-bit.
+//typedef qint64 int64_t;
+//@}
+
+
+#endif
diff --git a/src/tests.cpp b/src/tests.cpp
new file mode 100644 (file)
index 0000000..6582563
--- /dev/null
@@ -0,0 +1,122 @@
+//*****************************************************************
+/*
+  JackTrip: A System for High-Quality Audio Network Performance
+  over the Internet
+
+  Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
+  SoundWIRE group at CCRMA, Stanford University.
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+  
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+*/
+//*****************************************************************
+
+/**
+ * \file tests.cpp
+ * \author Juan-Pablo Caceres
+ * \date June 2008
+ */
+#include <iostream>
+#include <unistd.h>
+#include <getopt.h>
+
+
+#include "JackAudioInterface.h"
+#include "UdpDataProtocol.h"
+#include "RingBuffer.h"
+#include "JackTrip.h"
+#include "Settings.h"
+#include "TestRingBuffer.h"
+#include "jacktrip_globals.h"
+
+using namespace std;
+
+void tests()
+{
+  // Test JackTrip
+  //================================================================
+  //JackTrip jacktrip1;
+  //jacktrip1.startThreads();
+
+  //JackTrip jacktrip2;
+  //jacktrip2.startThreads();
+  /*
+  // TestRingBuffer
+  //================================================================
+  TestRingBufferWrite tw;
+  TestRingBufferRead tr;
+  tr.start();
+  tw.start();
+  */
+
+  /*
+  // Test RingBuffer
+  //================================================================
+  RingBuffer rb(2,2);
+
+  int8_t* writeSlot;
+  writeSlot = new int8_t[2];
+  writeSlot[0] = *"a";
+  writeSlot[1] = *"b";
+  std::cout << *writeSlot << std::endl;
+  std::cout << writeSlot[0] << std::endl;
+  std::cout << writeSlot[1] << std::endl;
+  std::cout << *(writeSlot+1) << std::endl;
+  rb.writeSlot(writeSlot);
+
+  int8_t* readSlot;
+  readSlot = new int8_t[2];
+  rb.readSlot(readSlot);
+  std::cout << *(readSlot) << std::endl;
+  std::cout << *(readSlot+1) << std::endl;
+  */
+
+
+  /*
+  // Test UDP Socket
+  //================================================================
+  UdpDataProtocol udp_rec(RECEIVER, "192.168.1.4");
+  UdpDataProtocol udp_send(SENDER, "192.168.1.4");
+  udp_rec.start();
+  udp_send.start();
+  */
+
+  /*
+  // Test JackAudioInterface
+  //================================================================
+  JackAudioInterface jack_test(4);
+  cout << "SR: " << jack_test.getSampleRate() << endl;
+  cout << "Buffer Size: " << jack_test.getBufferSize() << endl;
+  jack_test.setProcessCallback(process);
+  jack_test.startProcess();
+  */
+
+
+  while (true)
+    {
+      //cout << "SR: " << test.getSampleRate() << endl;
+      //cout << "Buffer Size: " << test.getBufferSize() << endl;
+      usleep(1000000);
+      //usleep(1);
+    }
+
+}