diff --git a/ChangeLog b/ChangeLog index 7d39661f..60b40651 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,33 +1,32 @@ ---------------------------- - Contributors ---------------------------- - -Dmitry Baikov -Gabriel M. Beddingfield -Steven Chamberlain -Thom Johansen -Thibault LeMeur -Tom Szilagyi -Andrzej Szombierski -Kjetil S.Matheussen -Pieter Palmers -Tim Blechmann -Marc-Olivier Barre -Nedko Arnaudov -Fernando Lopez-Lezcano -Romain Moret -Florian Faber -Michael Voigt -Torben Hohn -Paul Davis -Peter L Jones -Devin Anderson -Josh Green -Mario Lang +--------------------------- + Contributors +--------------------------- + +Dmitry Baikov +Gabriel M. Beddingfield +Steven Chamberlain +Thom Johansen +Thibault LeMeur +Tom Szilagyi +Andrzej Szombierski +Kjetil S.Matheussen +Pieter Palmers +Tim Blechmann +Marc-Olivier Barre +Nedko Arnaudov +Fernando Lopez-Lezcano +Romain Moret +Florian Faber +Michael Voigt +Torben Hohn +Paul Davis +Peter L Jones +Devin Anderson +Josh Green +Mario Lang Arnold Krille Jan Engelhardt Adrian Knoth -David Garcia Garzon Valerio Pilo --------------------------- @@ -107,7 +106,7 @@ Valerio Pilo * jack_client_has_session_callback implementation. * Fix jdelay for new latency API. - * Check requested buffer size and limit to 1..8192 - avoids weird behaviour caused by jack_bufsize foobar. + * Check requested buffer size and limit to 1..8192 - avoids wierd behaviour caused by jack_bufsize foobar. * jack_port_type_get_buffer_size implementation. * Stop using alloca and allocate buffer on the heap for alsa_io. * Rename jdelay to jack_iodelay as per Fons' request. @@ -1770,4 +1769,4 @@ Valerio Pilo 2006-09-03 Stephane Letz - * First import of version 0.58 base code + * First import of version 0.58 base code diff --git a/common/JackAudioAdapterInterface.cpp b/common/JackAudioAdapterInterface.cpp index 738363b6..cb589893 100644 --- a/common/JackAudioAdapterInterface.cpp +++ b/common/JackAudioAdapterInterface.cpp @@ -17,9 +17,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef __APPLE__ +#include +#endif + #include "JackAudioAdapter.h" +#ifndef MY_TARGET_OS_IPHONE #include "JackLibSampleRateResampler.h" -#include "JackTime.h" +#endif +#include "JackTime.h" #include namespace Jack @@ -66,11 +72,11 @@ namespace Jack fprintf(file, buffer); sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines"); fprintf(file, buffer); - - fprintf(file, "\n unset multiplot\n"); + + fprintf(file, "\n unset multiplot\n"); fprintf(file, "set output 'AdapterTiming1.svg\n"); fprintf(file, "set terminal svg\n"); - + fprintf(file, "set multiplot\n"); fprintf(file, "set grid\n"); fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" @@ -84,9 +90,9 @@ namespace Jack fprintf(file, buffer); fprintf(file, "unset multiplot\n"); fprintf(file, "unset output\n"); - + fclose(file); - + // Adapter timing 2 file = fopen("AdapterTiming2.plot", "w"); fprintf(file, "set multiplot\n"); @@ -100,11 +106,11 @@ namespace Jack fprintf(file, buffer); sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines"); fprintf(file, buffer); - - fprintf(file, "\n unset multiplot\n"); + + fprintf(file, "\n unset multiplot\n"); fprintf(file, "set output 'AdapterTiming2.svg\n"); fprintf(file, "set terminal svg\n"); - + fprintf(file, "set multiplot\n"); fprintf(file, "set grid\n"); fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" @@ -118,7 +124,7 @@ namespace Jack fprintf(file, buffer); fprintf(file, "unset multiplot\n"); fprintf(file, "unset output\n"); - + fclose(file); // Adapter timing 3 @@ -134,11 +140,11 @@ namespace Jack fprintf(file, buffer); sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines"); fprintf(file, buffer); - - fprintf(file, "\n unset multiplot\n"); + + fprintf(file, "\n unset multiplot\n"); fprintf(file, "set output 'AdapterTiming3.svg\n"); fprintf(file, "set terminal svg\n"); - + fprintf(file, "set multiplot\n"); fprintf(file, "set grid\n"); fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" @@ -152,7 +158,7 @@ namespace Jack fprintf(file, buffer); fprintf(file, "unset multiplot\n"); fprintf(file, "unset output\n"); - + fclose(file); } @@ -162,47 +168,51 @@ namespace Jack { fRingbufferCurSize *= 2; } - + void JackAudioAdapterInterface::AdaptRingBufferSize() { if (fHostBufferSize > fAdaptedBufferSize) fRingbufferCurSize = 4 * fHostBufferSize; - else + else fRingbufferCurSize = 4 * fAdaptedBufferSize; } - + void JackAudioAdapterInterface::ResetRingBuffers() { - if (fRingbufferCurSize > DEFAULT_RB_SIZE) + if (fRingbufferCurSize > DEFAULT_RB_SIZE) fRingbufferCurSize = DEFAULT_RB_SIZE; - + for (int i = 0; i < fCaptureChannels; i++) fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); for (int i = 0; i < fPlaybackChannels; i++) fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); } - + void JackAudioAdapterInterface::Reset() { ResetRingBuffers(); fRunning = false; } +#ifdef MY_TARGET_OS_IPHONE + void JackAudioAdapterInterface::Create() + {} +#else void JackAudioAdapterInterface::Create() { //ringbuffers fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; - + if (fAdaptative) { AdaptRingBufferSize(); jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize); } else { - if (fRingbufferCurSize > DEFAULT_RB_SIZE) + if (fRingbufferCurSize > DEFAULT_RB_SIZE) fRingbufferCurSize = DEFAULT_RB_SIZE; jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize); } - + for (int i = 0; i < fCaptureChannels; i++ ) { fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality); fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); @@ -211,12 +221,13 @@ namespace Jack fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality); fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); } - + if (fCaptureChannels > 0) jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); if (fPlaybackChannels > 0) jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); } +#endif void JackAudioAdapterInterface::Destroy() { @@ -228,39 +239,45 @@ namespace Jack delete[] fCaptureRingBuffer; delete[] fPlaybackRingBuffer; } - + int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames) { bool failure = false; fRunning = true; - + // Finer estimation of the position in the ringbuffer int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0; - + double ratio = 1; - + // TODO : done like this just to avoid crash when input only or output only... if (fCaptureChannels > 0) ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames); else if (fPlaybackChannels > 0) ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames); - + #ifdef JACK_MONITOR - if (fCaptureRingBuffer[0] != NULL) + if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL) fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace()); #endif - + // Push/pull from ringbuffer for (int i = 0; i < fCaptureChannels; i++) { fCaptureRingBuffer[i]->SetRatio(ratio); - if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) - failure = true; + if (inputBuffer[i]) { + if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) { + failure = true; + } + } } for (int i = 0; i < fPlaybackChannels; i++) { fPlaybackRingBuffer[i]->SetRatio(1/ratio); - if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) - failure = true; + if (outputBuffer[i]) { + if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) { + failure = true; + } + } } // Reset all ringbuffers in case of failure if (failure) { @@ -276,26 +293,32 @@ namespace Jack } } - int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames) + int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames) { fPullAndPushTime = GetMicroSeconds(); if (!fRunning) return 0; int res = 0; - + // Push/pull from ringbuffer for (int i = 0; i < fCaptureChannels; i++) { - if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) - res = -1; + if (inputBuffer[i]) { + if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) { + res = -1; + } + } } for (int i = 0; i < fPlaybackChannels; i++) { - if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) - res = -1; + if (outputBuffer[i]) { + if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) { + res = -1; + } + } } - + return res; } - + } // namespace diff --git a/common/JackAudioAdapterInterface.h b/common/JackAudioAdapterInterface.h index 7a60ba23..bb79c75c 100644 --- a/common/JackAudioAdapterInterface.h +++ b/common/JackAudioAdapterInterface.h @@ -102,7 +102,7 @@ namespace Jack public: - JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ): + JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE): fCaptureChannels ( 0 ), fPlaybackChannels ( 0 ), fHostBufferSize ( buffer_size ), @@ -112,19 +112,37 @@ namespace Jack fPIControler(sample_rate / sample_rate, 256), fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL), fQuality(0), - fRingbufferCurSize(DEFAULT_ADAPTATIVE_SIZE), + fRingbufferCurSize(ring_buffer_size), fPullAndPushTime(0), fRunning(false), fAdaptative(true) {} + JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, + jack_nframes_t host_sample_rate, + jack_nframes_t adapted_buffer_size, + jack_nframes_t adapted_sample_rate, + jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE ) : + fCaptureChannels ( 0 ), + fPlaybackChannels ( 0 ), + fHostBufferSize ( host_buffer_size ), + fHostSampleRate ( host_sample_rate ), + fAdaptedBufferSize ( adapted_buffer_size), + fAdaptedSampleRate ( adapted_sample_rate ), + fPIControler(host_sample_rate / host_sample_rate, 256), + fQuality(0), + fRingbufferCurSize(ring_buffer_size), + fPullAndPushTime(0), + fRunning(false), + fAdaptative(true) + {} virtual ~JackAudioAdapterInterface() {} virtual void Reset(); - void Create(); - void Destroy(); + virtual void Create(); + virtual void Destroy(); virtual int Open() { @@ -194,18 +212,18 @@ namespace Jack int GetInputs() { - jack_log ( "JackAudioAdapterInterface::GetInputs %d", fCaptureChannels ); + //jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels); return fCaptureChannels; } int GetOutputs() { - jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels ); + //jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels); return fPlaybackChannels; } - int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames); - int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames); + int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); + int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); }; diff --git a/common/JackEngineProfiling.cpp b/common/JackEngineProfiling.cpp index 4557fec9..0f2814a3 100644 --- a/common/JackEngineProfiling.cpp +++ b/common/JackEngineProfiling.cpp @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -34,7 +34,7 @@ namespace Jack JackEngineProfiling::JackEngineProfiling():fAudioCycle(0),fMeasuredClient(0) { jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024)); - + // Force memory page in memset(fProfileTable, 0, sizeof(fProfileTable)); } @@ -47,32 +47,32 @@ JackEngineProfiling::~JackEngineProfiling() if (!fStream.is_open()) { jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file"); } else { - + // For each measured point for (int i = 2; i < TIME_POINTS; i++) { - + // Driver timing values long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin); long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin); - + if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0) continue; // Skip non valid cycles - + // Print driver delta and end cycle fStream << d1 << "\t" << d2 << "\t"; - + // For each measured client - for (unsigned int j = 0; j < fMeasuredClient; j++) { - + for (unsigned int j = 0; j < fMeasuredClient; j++) { + int ref = fIntervalTable[j].fRefNum; - - // Is valid client cycle - if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) { - + + // Is valid client cycle + if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) { + long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin); long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin); long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin); - + fStream << ref << "\t" ; fStream << ((d5 > 0) ? d5 : 0) << "\t"; fStream << ((d6 > 0) ? d6 : 0) << "\t" ; @@ -80,57 +80,57 @@ JackEngineProfiling::~JackEngineProfiling() fStream << ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0) << "\t" ; fStream << ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0) << "\t" ; fStream << fProfileTable[i].fClientTable[ref].fStatus << "\t" ;; - + } else { // Print tabs fStream << "\t \t \t \t \t \t \t"; } } - + // Terminate line fStream << std::endl; } } - + // Driver period std::ofstream fStream1("Timing1.plot", std::ios_base::ate); - + if (!fStream1.is_open()) { jack_error("JackEngineProfiling::Save cannot open Timing1.plot file"); } else { - + fStream1 << "set grid\n"; fStream1 << "set title \"Audio driver timing\"\n"; fStream1 << "set xlabel \"audio cycles\"\n"; fStream1 << "set ylabel \"usec\"\n"; fStream1 << "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n"; - + fStream1 << "set output 'Timing1.svg\n"; fStream1 << "set terminal svg\n"; - + fStream1 << "set grid\n"; fStream1 << "set title \"Audio driver timing\"\n"; fStream1 << "set xlabel \"audio cycles\"\n"; fStream1 << "set ylabel \"usec\"\n"; fStream1 << "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n"; - fStream1 << "unset output\n"; + fStream1 << "unset output\n"; } - + // Driver end date std::ofstream fStream2("Timing2.plot", std::ios_base::ate); - + if (!fStream2.is_open()) { jack_error("JackEngineProfiling::Save cannot open Timing2.plot file"); } else { - + fStream2 << "set grid\n"; fStream2 << "set title \"Driver end date\"\n"; fStream2 << "set xlabel \"audio cycles\"\n"; fStream2 << "set ylabel \"usec\"\n"; fStream2 << "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n"; - + fStream2 << "set output 'Timing2.svg\n"; fStream2 << "set terminal svg\n"; - + fStream2 << "set grid\n"; fStream2 << "set title \"Driver end date\"\n"; fStream2 << "set xlabel \"audio cycles\"\n"; @@ -138,15 +138,15 @@ JackEngineProfiling::~JackEngineProfiling() fStream2 << "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n"; fStream2 << "unset output\n"; } - + // Clients end date if (fMeasuredClient > 0) { std::ofstream fStream3("Timing3.plot", std::ios_base::ate); - + if (!fStream3.is_open()) { jack_error("JackEngineProfiling::Save cannot open Timing3.plot file"); } else { - + fStream3 << "set multiplot\n"; fStream3 << "set grid\n"; fStream3 << "set title \"Clients end date\"\n"; @@ -170,11 +170,11 @@ JackEngineProfiling::~JackEngineProfiling() fStream3 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) - 1 << " title \"" << fIntervalTable[i].fName << "\" with lines,"; } } - - fStream3 << "\n unset multiplot\n"; + + fStream3 << "\n unset multiplot\n"; fStream3 << "set output 'Timing3.svg\n"; fStream3 << "set terminal svg\n"; - + fStream3 << "set multiplot\n"; fStream3 << "set grid\n"; fStream3 << "set title \"Clients end date\"\n"; @@ -206,11 +206,11 @@ JackEngineProfiling::~JackEngineProfiling() // Clients scheduling if (fMeasuredClient > 0) { std::ofstream fStream4("Timing4.plot", std::ios_base::ate); - + if (!fStream4.is_open()) { jack_error("JackEngineProfiling::Save cannot open Timing4.plot file"); } else { - + fStream4 << "set multiplot\n"; fStream4 << "set grid\n"; fStream4 << "set title \"Clients scheduling latency\"\n"; @@ -224,11 +224,11 @@ JackEngineProfiling::~JackEngineProfiling() fStream4 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) << " title \"" << fIntervalTable[i].fName << "\" with lines,"; } } - - fStream4 << "\n unset multiplot\n"; + + fStream4 << "\n unset multiplot\n"; fStream4 << "set output 'Timing4.svg\n"; fStream4 << "set terminal svg\n"; - + fStream4 << "set multiplot\n"; fStream4 << "set grid\n"; fStream4 << "set title \"Clients scheduling latency\"\n"; @@ -246,7 +246,7 @@ JackEngineProfiling::~JackEngineProfiling() fStream4 << "unset output\n"; } } - + // Clients duration if (fMeasuredClient > 0) { std::ofstream fStream5("Timing5.plot", std::ios_base::ate); @@ -254,7 +254,7 @@ JackEngineProfiling::~JackEngineProfiling() if (!fStream5.is_open()) { jack_error("JackEngineProfiling::Save cannot open Timing5.plot file"); } else { - + fStream5 << "set multiplot\n"; fStream5 << "set grid\n"; fStream5 << "set title \"Clients duration\"\n"; @@ -268,11 +268,11 @@ JackEngineProfiling::~JackEngineProfiling() fStream5 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) + 1 << " title \"" << fIntervalTable[i].fName << "\" with lines,"; } } - - fStream5 << "\n unset multiplot\n"; + + fStream5 << "\n unset multiplot\n"; fStream5 << "set output 'Timing5.svg\n"; fStream5 << "set terminal svg\n"; - + fStream5 << "set multiplot\n"; fStream5 << "set grid\n"; fStream5 << "set title \"Clients duration\"\n"; @@ -290,7 +290,7 @@ JackEngineProfiling::~JackEngineProfiling() fStream5 << "unset output\n"; } } - + std::ofstream fStream6("Timings.html", std::ios_base::ate); if (!fStream6.is_open()) { jack_error("JackEngineProfiling::Save cannot open Timings.html file"); @@ -315,8 +315,8 @@ JackEngineProfiling::~JackEngineProfiling() fStream6 << "
Timing5
"; fStream6 << " \n"; fStream6 << "\n"; - } - + } + std::ofstream fStream7("generate_timings", std::ios_base::ate); if (!fStream7.is_open()) { jack_error("JackEngineProfiling::Save cannot open generate_timings file"); @@ -326,7 +326,7 @@ JackEngineProfiling::~JackEngineProfiling() fStream7 << "gnuplot -persist Timing3.plot\n"; fStream7 << "gnuplot -persist Timing4.plot\n"; fStream7 << "gnuplot -persist Timing5.plot\n"; - } + } } bool JackEngineProfiling::CheckClient(const char* name, int cur_point) @@ -340,14 +340,14 @@ bool JackEngineProfiling::CheckClient(const char* name, int cur_point) return false; } -void JackEngineProfiling::Profile(JackClientInterface** table, - JackGraphManager* manager, +void JackEngineProfiling::Profile(JackClientInterface** table, + JackGraphManager* manager, jack_time_t period_usecs, - jack_time_t cur_cycle_begin, + jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) { fAudioCycle = (fAudioCycle + 1) % TIME_POINTS; - + // Keeps cycle data fProfileTable[fAudioCycle].fPeriodUsecs = period_usecs; fProfileTable[fAudioCycle].fCurCycleBegin = cur_cycle_begin; @@ -358,7 +358,7 @@ void JackEngineProfiling::Profile(JackClientInterface** table, JackClientInterface* client = table[i]; JackClientTiming* timing = manager->GetClientTiming(i); if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) { - + if (!CheckClient(client->GetClientControl()->fName, fAudioCycle)) { // Keep new measured client fIntervalTable[fMeasuredClient].fRefNum = i; @@ -380,5 +380,5 @@ JackTimingMeasure* JackEngineProfiling::GetCurMeasure() { return &fProfileTable[fAudioCycle]; } - + } // end of namespace diff --git a/common/JackFilters.h b/common/JackFilters.h index 76bf7ecd..23980900 100644 --- a/common/JackFilters.h +++ b/common/JackFilters.h @@ -20,33 +20,41 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __JackFilters__ #define __JackFilters__ +#ifdef __APPLE__ +#include +#endif + #include "jack.h" +#ifndef MY_TARGET_OS_IPHONE #include "JackAtomicState.h" +#endif #include #include namespace Jack { +#ifndef TARGET_OS_IPHONE + #define MAX_SIZE 64 - - struct JackFilter + + struct JackFilter { - + jack_time_t fTable[MAX_SIZE]; - + JackFilter() { for (int i = 0; i < MAX_SIZE; i++) fTable[i] = 0; } - + void AddValue(jack_time_t val) { memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1)); fTable[0] = val; } - + jack_time_t GetVal() { jack_time_t mean = 0; @@ -54,14 +62,14 @@ namespace Jack mean += fTable[i]; return mean / MAX_SIZE; } - + } POST_PACKED_STRUCTURE; - + class JackDelayLockedLoop { - + private: - + jack_nframes_t fFrames; jack_time_t fCurrentWakeup; jack_time_t fCurrentCallback; @@ -72,17 +80,17 @@ namespace Jack jack_time_t fPeriodUsecs; float fFilterCoefficient; /* set once, never altered */ bool fUpdating; - + public: - + JackDelayLockedLoop() {} - + JackDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate) { Init(buffer_size, sample_rate); } - + void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate) { fFrames = 0; @@ -95,7 +103,7 @@ namespace Jack fSampleRate = sample_rate; fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // in microsec } - + void Init(jack_time_t callback_usecs) { fFrames = 0; @@ -104,7 +112,7 @@ namespace Jack fCurrentCallback = callback_usecs; fNextWakeUp = callback_usecs + fPeriodUsecs; } - + void IncFrame(jack_time_t callback_usecs) { float delta = (int64_t)callback_usecs - (int64_t)fNextWakeUp; @@ -114,41 +122,41 @@ namespace Jack fSecondOrderIntegrator += 0.5f * fFilterCoefficient * delta; fNextWakeUp = fCurrentWakeup + fPeriodUsecs + (int64_t) floorf((fFilterCoefficient * (delta + fSecondOrderIntegrator))); } - + jack_nframes_t Time2Frames(jack_time_t time) { long delta = (long) rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * fBufferSize); return (delta < 0) ? ((fFrames > 0) ? fFrames : 1) : (fFrames + delta); } - + jack_time_t Frames2Time(jack_nframes_t frames) { long delta = (long) rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / fBufferSize); return (delta < 0) ? ((fCurrentWakeup > 0) ? fCurrentWakeup : 1) : (fCurrentWakeup + delta); } - + jack_nframes_t CurFrame() { return fFrames; } - + jack_time_t CurTime() { return fCurrentWakeup; } - + } POST_PACKED_STRUCTURE; - + class JackAtomicDelayLockedLoop : public JackAtomicState { public: - + JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate) { fState[0].Init(buffer_size, sample_rate); fState[1].Init(buffer_size, sample_rate); } - + void Init(jack_time_t callback_usecs) { JackDelayLockedLoop* dll = WriteNextStateStart(); @@ -156,7 +164,7 @@ namespace Jack WriteNextStateStop(); TrySwitchState(); // always succeed since there is only one writer } - + void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate) { JackDelayLockedLoop* dll = WriteNextStateStart(); @@ -164,7 +172,7 @@ namespace Jack WriteNextStateStop(); TrySwitchState(); // always succeed since there is only one writer } - + void IncFrame(jack_time_t callback_usecs) { JackDelayLockedLoop* dll = WriteNextStateStart(); @@ -172,44 +180,46 @@ namespace Jack WriteNextStateStop(); TrySwitchState(); // always succeed since there is only one writer } - + jack_nframes_t Time2Frames(jack_time_t time) { UInt16 next_index = GetCurrentIndex(); UInt16 cur_index; jack_nframes_t res; - + do { cur_index = next_index; res = ReadCurrentState()->Time2Frames(time); next_index = GetCurrentIndex(); } while (cur_index != next_index); // Until a coherent state has been read - + return res; } - + jack_time_t Frames2Time(jack_nframes_t frames) { UInt16 next_index = GetCurrentIndex(); UInt16 cur_index; jack_time_t res; - + do { cur_index = next_index; res = ReadCurrentState()->Frames2Time(frames); next_index = GetCurrentIndex(); } while (cur_index != next_index); // Until a coherent state has been read - + return res; } } POST_PACKED_STRUCTURE; - + +#endif + /* Torben Hohn PI controler from JACK1 */ - + struct JackPIControler { - + double resample_mean; double static_resample_factor; @@ -224,12 +234,12 @@ namespace Jack double pclamp; double controlquant; int smooth_size; - + double hann(double x) { return 0.5 * (1.0 - cos(2 * M_PI * x)); } - + JackPIControler(double resample_factor, int fir_size) { resample_mean = resample_factor; @@ -239,7 +249,7 @@ namespace Jack offset_differential_index = 0; offset_integral = 0.0; smooth_size = fir_size; - + for (int i = 0; i < fir_size; i++) { offset_array[i] = 0.0; window_array[i] = hann(double(i) / (double(fir_size) - 1.0)); @@ -251,19 +261,19 @@ namespace Jack pclamp = 15.0; controlquant = 10000.0; } - + ~JackPIControler() { delete[] offset_array; delete[] window_array; } - + void Init(double resample_factor) { resample_mean = resample_factor; static_resample_factor = resample_factor; } - + /* double GetRatio(int fill_level) { @@ -271,14 +281,14 @@ namespace Jack // Save offset. offset_array[(offset_differential_index++) % smooth_size] = offset; - + // Build the mean of the windowed offset array basically fir lowpassing. double smooth_offset = 0.0; for (int i = 0; i < smooth_size; i++) { smooth_offset += offset_array[(i + offset_differential_index - 1) % smooth_size] * window_array[i]; } smooth_offset /= double(smooth_size); - + // This is the integral of the smoothed_offset offset_integral += smooth_offset; @@ -286,13 +296,13 @@ namespace Jack // It only used in the P component and the I component is used for the fine tuning anyways. if (fabs(smooth_offset) < pclamp) smooth_offset = 0.0; - - // Ok, now this is the PI controller. + + // Ok, now this is the PI controller. // u(t) = K * (e(t) + 1/T \int e(t') dt') - // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T - double current_resample_factor + // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T + double current_resample_factor = static_resample_factor - smooth_offset / catch_factor - offset_integral / catch_factor / catch_factor2; - + // Now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt. current_resample_factor = floor((current_resample_factor - resample_mean) * controlquant + 0.5) / controlquant + resample_mean; @@ -309,25 +319,25 @@ namespace Jack // This is the integral of the smoothed_offset offset_integral += smooth_offset; - // Ok, now this is the PI controller. + // Ok, now this is the PI controller. // u(t) = K * (e(t) + 1/T \int e(t') dt') - // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T + // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2; } - + void OurOfBounds() { int i; // Set the resample_rate... we need to adjust the offset integral, to do this. // first look at the PI controller, this code is just a special case, which should never execute once - // everything is swung in. + // everything is swung in. offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2; // Also clear the array. we are beginning a new control cycle. for (i = 0; i < smooth_size; i++) { offset_array[i] = 0.0; } } - + }; } diff --git a/common/JackGlobals.h b/common/JackGlobals.h index 63dc9ab2..38e922d4 100644 --- a/common/JackGlobals.h +++ b/common/JackGlobals.h @@ -23,12 +23,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackPlatformPlug.h" #include "JackConstants.h" -#ifdef __CLIENTDEBUG__ +#ifdef __CLIENTDEBUG__ #include #include #include #include -#endif +#endif namespace Jack { @@ -45,7 +45,7 @@ struct JackGlobals { #ifndef WIN32 static jack_thread_creator_t fJackThreadCreator; #endif - + #ifdef __CLIENTDEBUG__ static std::ofstream* fStream; static void CheckContext(const char* name); diff --git a/common/JackNetAPI.cpp b/common/JackNetAPI.cpp new file mode 100644 index 00000000..3f130771 --- /dev/null +++ b/common/JackNetAPI.cpp @@ -0,0 +1,1005 @@ +/* +Copyright (C) 2009 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include +#include "JackNetInterface.h" +#include "JackPlatformPlug.h" +#include "JackError.h" +#include "JackTime.h" +#include "JackException.h" +#include "JackAudioAdapterInterface.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + // NetJack common API + + #define MASTER_NAME_SIZE 256 + + enum JackNetMode { + + JackFastMode = 'f', + JackNormalMode = 'n', + JackSlowMode = 's', + }; + + enum JackNetEncoder { + + JackFloatEncoder = 0, + JackIntEncoder = 1, + JackCeltEncoder = 2, + }; + + typedef struct { + + int audio_input; + int audio_output; + int midi_input; + int midi_output; + int mtu; + int time_out; // in millisecond, -1 means in infinite + int encoder; + int kbps; // KB per second for CELT encoder + char mode; + + } jack_slave_t; + + typedef struct { + + jack_nframes_t buffer_size; + jack_nframes_t sample_rate; + char master_name[MASTER_NAME_SIZE]; + + } jack_master_t; + + // NetJack slave API + + typedef struct _jack_net_slave jack_net_slave_t; + + typedef int (* JackNetSlaveProcessCallback) (jack_nframes_t buffer_size, + int audio_input, + float** audio_input_buffer, + int midi_input, + void** midi_input_buffer, + int audio_output, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, + void* data); + + typedef int (*JackNetSlaveBufferSizeCallback) (jack_nframes_t nframes, void *arg); + typedef int (*JackNetSlaveSampleRateCallback) (jack_nframes_t nframes, void *arg); + typedef void (*JackNetSlaveShutdownCallback) (void* data); + + SERVER_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result); + SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net); + + SERVER_EXPORT int jack_net_slave_activate(jack_net_slave_t* net); + SERVER_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net); + + SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t * net, JackNetSlaveProcessCallback net_callback, void *arg); + SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg); + SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg); + SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg); + + // NetJack master API + + typedef struct _jack_net_master jack_net_master_t; + + SERVER_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result); + SERVER_EXPORT int jack_net_master_close(jack_net_master_t* net); + + SERVER_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); + SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); + + // NetJack adapter API + + typedef struct _jack_adapter jack_adapter_t; + + SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, + jack_nframes_t host_buffer_size, + jack_nframes_t host_sample_rate, + jack_nframes_t adapted_buffer_size, + jack_nframes_t adapted_sample_rate); + SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter); + SERVER_EXPORT void jack_flush_adapter(jack_adapter_t* adapter); + + SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); + SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); + +#ifdef __cplusplus +} +#endif + +namespace Jack +{ + +struct JackNetExtMaster : public JackNetMasterInterface { + + // Data buffers + float** fAudioCaptureBuffer; + float** fAudioPlaybackBuffer; + + JackMidiBuffer** fMidiCaptureBuffer; + JackMidiBuffer** fMidiPlaybackBuffer; + + jack_master_t fRequest; + + JackNetExtMaster(const char* ip, + int port, + const char* name, + jack_master_t* request) + { + fRunning = true; + assert(strlen(ip) < 32); + strcpy(fMulticastIP, ip); + fSocket.SetPort(port); + fRequest.buffer_size = request->buffer_size; + fRequest.sample_rate = request->sample_rate; + fAudioCaptureBuffer = NULL; + fAudioPlaybackBuffer = NULL; + fMidiCaptureBuffer = NULL; + fMidiPlaybackBuffer = NULL; + } + + virtual ~JackNetExtMaster() + {} + + int Open(jack_slave_t* result) + { + // Init socket API (win32) + if (SocketAPIInit() < 0) { + fprintf(stderr, "Can't init Socket API, exiting...\n"); + return -1; + } + + // Request socket + if (fSocket.NewSocket() == SOCKET_ERROR) { + fprintf(stderr, "Can't create the network management input socket : %s\n", StrError(NET_ERROR_CODE)); + return -1; + } + + // Bind the socket to the local port + if (fSocket.Bind() == SOCKET_ERROR) { + fprintf(stderr, "Can't bind the network manager socket : %s\n", StrError(NET_ERROR_CODE)); + fSocket.Close(); + return -1; + } + + // Join multicast group + if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) + fprintf(stderr, "Can't join multicast group : %s\n", StrError(NET_ERROR_CODE)); + + // Local loop + if (fSocket.SetLocalLoop() == SOCKET_ERROR) + fprintf(stderr, "Can't set local loop : %s\n", StrError(NET_ERROR_CODE)); + + // Set a timeout on the multicast receive (the thread can now be cancelled) + if (fSocket.SetTimeOut(2000000) == SOCKET_ERROR) + fprintf(stderr, "Can't set timeout : %s\n", StrError(NET_ERROR_CODE)); + + //main loop, wait for data, deal with it and wait again + //utility variables + int attempt = 0; + int rx_bytes = 0; + + do + { + session_params_t net_params; + rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0); + SessionParamsNToH(&net_params, &fParams); + + if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { + fprintf(stderr, "Error in receive : %s\n", StrError(NET_ERROR_CODE)); + if (++attempt == 10) { + fprintf(stderr, "Can't receive on the socket, exiting net manager.\n" ); + goto error; + } + } + + if (rx_bytes == sizeof(session_params_t )) { + + switch (GetPacketType(&fParams)) { + + case SLAVE_AVAILABLE: + if (MasterInit() == 0) { + SessionParamsDisplay(&fParams); + fRunning = false; + } else { + fprintf(stderr, "Can't init new net master...\n"); + goto error; + } + jack_info ( "Waiting for a slave..." ); + break; + + case KILL_MASTER: + break; + + default: + break; + } + } + } + while (fRunning); + + // Set result paramaters + result->audio_input = fParams.fSendAudioChannels; + result->audio_output = fParams.fReturnAudioChannels; + result->midi_input = fParams.fSendMidiChannels; + result->midi_output = fParams.fReturnMidiChannels; + result->mtu = fParams.fMtu; + result->mode = fParams.fNetworkMode; + return 0; + + error: + fSocket.Close(); + return -1; + } + + int MasterInit() + { + // Check MASTER <==> SLAVE network protocol coherency + if (fParams.fProtocolVersion != MASTER_PROTOCOL) { + fprintf(stderr, "Error : slave is running with a different protocol %s\n", fParams.fName); + return -1; + } + + // Settings + fSocket.GetName(fParams.fMasterNetName); + fParams.fID = 1; + fParams.fSampleEncoder = JackFloatEncoder; + fParams.fPeriodSize = fRequest.buffer_size; + fParams.fSampleRate = fRequest.sample_rate; + + // Close request socket + fSocket.Close(); + + // Network slave init + if (!JackNetMasterInterface::Init()) + return -1; + + // Set global parameters + if (!SetParams()) + return -1; + + AllocPorts(); + return 0; + } + + int Close() + { + fSocket.Close(); + FreePorts(); + return 0; + } + + void AllocPorts() + { + unsigned int port_index; + + // Set buffers + if (fParams.fSendAudioChannels > 0) { + fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels]; + for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { + fAudioCaptureBuffer[port_index] = new float[fParams.fPeriodSize]; + fNetAudioCaptureBuffer->SetBuffer(port_index, fAudioCaptureBuffer[port_index]); + } + } + + if (fParams.fSendMidiChannels > 0) { + fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels]; + for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { + fMidiCaptureBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiCaptureBuffer->SetBuffer(port_index, fMidiCaptureBuffer[port_index]); + } + } + + if (fParams.fReturnAudioChannels > 0) { + fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels]; + for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { + fAudioPlaybackBuffer[port_index] = new float[fParams.fPeriodSize]; + fNetAudioPlaybackBuffer->SetBuffer(port_index, fAudioPlaybackBuffer[port_index]); + } + } + + if (fParams.fReturnMidiChannels > 0) { + fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels]; + for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { + fMidiPlaybackBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiPlaybackBuffer->SetBuffer(port_index, fMidiPlaybackBuffer[port_index]); + } + } + } + + void FreePorts() + { + unsigned int port_index; + + if (fAudioPlaybackBuffer) { + for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) + delete[] fAudioPlaybackBuffer[port_index]; + delete[] fAudioPlaybackBuffer; + fAudioPlaybackBuffer = NULL; + } + + if (fMidiPlaybackBuffer) { + for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) + delete[] (fMidiPlaybackBuffer[port_index]); + delete[] fMidiPlaybackBuffer; + fMidiPlaybackBuffer = NULL; + } + + if (fAudioCaptureBuffer) { + for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) + delete[] fAudioCaptureBuffer[port_index]; + delete[] fAudioCaptureBuffer; + fAudioCaptureBuffer = NULL; + } + + if (fMidiCaptureBuffer) { + for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) + delete[] fMidiCaptureBuffer[port_index]; + delete[] fMidiCaptureBuffer; + fMidiCaptureBuffer = NULL; + } + } + + int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) + { + try { + assert((unsigned int)audio_input == fParams.fReturnAudioChannels); + + for (int port_index = 0; port_index < audio_input; port_index++) { + fNetAudioPlaybackBuffer->SetBuffer(port_index, audio_input_buffer[port_index]); + } + + for (int port_index = 0; port_index < midi_input; port_index++) { + fNetMidiPlaybackBuffer->SetBuffer(port_index, ((JackMidiBuffer**)midi_input_buffer)[port_index]); + } + + if (SyncRecv() == SOCKET_ERROR) + return 0; + + DecodeSyncPacket(); + return DataRecv(); + + } catch (JackNetException& e) { + jack_error("Connection lost."); + return -1; + } + } + + int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) + { + try { + assert((unsigned int)audio_output == fParams.fSendAudioChannels); + + for (int port_index = 0; port_index < audio_output; port_index++) { + fNetAudioCaptureBuffer->SetBuffer(port_index, audio_output_buffer[port_index]); + } + + for (int port_index = 0; port_index < midi_output; port_index++) { + fNetMidiCaptureBuffer->SetBuffer(port_index, ((JackMidiBuffer**)midi_output_buffer)[port_index]); + } + + EncodeSyncPacket(); + + if (SyncSend() == SOCKET_ERROR) + return SOCKET_ERROR; + + return DataSend(); + + } catch (JackNetException& e) { + jack_error("Connection lost."); + return -1; + } + } + + // Transport + void EncodeTransportData() + {} + + void DecodeTransportData() + {} + +}; + +struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterface { + + JackThread fThread; + + JackNetSlaveProcessCallback fProcessCallback; + void* fProcessArg; + + JackNetSlaveShutdownCallback fShutdownCallback; + void* fShutdownArg; + + JackNetSlaveBufferSizeCallback fBufferSizeCallback; + void* fBufferSizeArg; + + JackNetSlaveSampleRateCallback fSampleRateCallback; + void* fSampleRateArg; + + //sample buffers + float** fAudioCaptureBuffer; + float** fAudioPlaybackBuffer; + + JackMidiBuffer** fMidiCaptureBuffer; + JackMidiBuffer** fMidiPlaybackBuffer; + + int fConnectTimeOut; + + JackNetExtSlave(const char* ip, + int port, + const char* name, + jack_slave_t* request) + :fThread(this), + fProcessCallback(NULL),fProcessArg(NULL), + fShutdownCallback(NULL), fShutdownArg(NULL), + fBufferSizeCallback(NULL), fBufferSizeArg(NULL), + fSampleRateCallback(NULL), fSampleRateArg(NULL), + fAudioCaptureBuffer(NULL), fAudioPlaybackBuffer(NULL), + fMidiCaptureBuffer(NULL), fMidiPlaybackBuffer(NULL) + { + char host_name[JACK_CLIENT_NAME_SIZE]; + + // Request parameters + assert(strlen(ip) < 32); + strcpy(fMulticastIP, ip); + + fParams.fMtu = request->mtu; + fParams.fTransportSync = 0; + fParams.fSendAudioChannels = request->audio_input; + fParams.fReturnAudioChannels = request->audio_output; + fParams.fSendMidiChannels = request->midi_input; + fParams.fReturnMidiChannels = request->midi_output; + fParams.fNetworkMode = request->mode; + fParams.fSampleEncoder = request->encoder; + fParams.fKBps = request->kbps; + fConnectTimeOut = request->time_out; + + // Create name with hostname and client name + GetHostName(host_name, JACK_CLIENT_NAME_SIZE); + snprintf(fParams.fName, JACK_CLIENT_NAME_SIZE, "%s_%s", host_name, name); + fSocket.GetName(fParams.fSlaveNetName); + + // Set the socket parameters + fSocket.SetPort(port); + fSocket.SetAddress(fMulticastIP, port); + } + + virtual ~JackNetExtSlave() + {} + + int Open(jack_master_t* result) + { + // Init network connection + if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) + return -1; + + // Then set global parameters + if (!SetParams()) + return -1; + + // Set result + if (result != NULL) { + result->buffer_size = fParams.fPeriodSize; + result->sample_rate = fParams.fSampleRate; + strcpy(result->master_name, fParams.fMasterNetName); + } + + AllocPorts(); + return 0; + } + + int Restart() + { + // If shutdown cb is set, then call it + if (fShutdownCallback) + fShutdownCallback(fShutdownArg); + + // Init complete network connection + if (!JackNetSlaveInterface::Init()) + return -1; + + // Then set global parameters + if (!SetParams()) + return -1; + + // We need to notify possibly new buffer size and sample rate (see Execute) + if (fBufferSizeCallback) + fBufferSizeCallback(fParams.fPeriodSize, fBufferSizeArg); + + if (fSampleRateCallback) + fSampleRateCallback(fParams.fSampleRate, fSampleRateArg); + + AllocPorts(); + return 0; + } + + int Close() + { + fSocket.Close(); + FreePorts(); + return 0; + } + + void AllocPorts() + { + unsigned int port_index; + + // Set buffers + fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels]; + for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { + fAudioCaptureBuffer[port_index] = new float[fParams.fPeriodSize]; + fNetAudioCaptureBuffer->SetBuffer(port_index, fAudioCaptureBuffer[port_index]); + } + + fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels]; + for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { + fMidiCaptureBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiCaptureBuffer->SetBuffer(port_index, fMidiCaptureBuffer[port_index]); + } + + fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels]; + for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { + fAudioPlaybackBuffer[port_index] = new float[fParams.fPeriodSize]; + fNetAudioPlaybackBuffer->SetBuffer(port_index, fAudioPlaybackBuffer[port_index]); + } + + fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels]; + for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { + fMidiPlaybackBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiPlaybackBuffer->SetBuffer(port_index, fMidiPlaybackBuffer[port_index]); + } + } + + void FreePorts() + { + unsigned int port_index; + + if (fAudioCaptureBuffer) { + for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) + delete[] fAudioCaptureBuffer[port_index]; + delete[] fAudioCaptureBuffer; + fAudioCaptureBuffer = NULL; + } + + if (fMidiCaptureBuffer) { + for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) + delete[] (fMidiCaptureBuffer[port_index]); + delete[] fMidiCaptureBuffer; + fMidiCaptureBuffer = NULL; + } + + if (fAudioPlaybackBuffer) { + for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) + delete[] fAudioPlaybackBuffer[port_index]; + delete[] fAudioPlaybackBuffer; + fAudioPlaybackBuffer = NULL; + } + + if (fMidiPlaybackBuffer) { + for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) + delete[] fMidiPlaybackBuffer[port_index]; + delete[] fMidiPlaybackBuffer; + fMidiPlaybackBuffer = NULL; + } + } + + // Transport + void EncodeTransportData() + {} + + void DecodeTransportData() + {} + + bool Init() + { + // Will do "something" on OSX only... + fThread.SetParams(float(fParams.fPeriodSize) / float(fParams.fSampleRate) * 1000000, 100 * 1000, 500 * 1000); + return (fThread.AcquireRealTime(80) == 0); // TODO: get a value from the server + } + + bool Execute() + { + try { + // Keep running even in case of error + while (fThread.GetStatus() == JackThread::kRunning) { + if (Process() == SOCKET_ERROR) + return false; + } + return false; + } catch (JackNetException& e) { + + // Otherwise just restart... + e.PrintMessage(); + fThread.DropRealTime(); + fThread.SetStatus(JackThread::kIniting); + FreePorts(); + Restart(); + if (Init()) { + fThread.SetStatus(JackThread::kRunning); + return true; + } else { + return false; + } + } + } + + int Read() + { + // Don't return -1 in case of sync recv failure + // we need the process to continue for network error detection + if (SyncRecv() == SOCKET_ERROR) + return 0; + + DecodeSyncPacket(); + return DataRecv(); + } + + int Write() + { + EncodeSyncPacket(); + + if (SyncSend() == SOCKET_ERROR) + return SOCKET_ERROR; + + return DataSend(); + } + + int Process() + { + // Read data from the network + // in case of fatal network error, stop the process + if (Read() == SOCKET_ERROR) + return SOCKET_ERROR; + + fProcessCallback(fParams.fPeriodSize, + fParams.fSendAudioChannels, + fAudioCaptureBuffer, + fParams.fSendMidiChannels, + (void**)fMidiCaptureBuffer, + fParams.fReturnAudioChannels, + fAudioPlaybackBuffer, + fParams.fReturnMidiChannels, + (void**)fMidiPlaybackBuffer, + fProcessArg); + + // Then write data to network + // in case of failure, stop process + if (Write() == SOCKET_ERROR) + return SOCKET_ERROR; + + return 0; + } + + int Start() + { + // Finish connection.. + if (!JackNetSlaveInterface::InitRendering()) { + return -1; + } + + return (fProcessCallback == 0) ? -1 : fThread.StartSync(); + } + + int Stop() + { + return (fProcessCallback == 0) ? -1 : fThread.Kill(); + } + + // Callback + int SetProcessCallback(JackNetSlaveProcessCallback net_callback, void *arg) + { + if (fThread.GetStatus() == JackThread::kRunning) { + return -1; + } else { + fProcessCallback = net_callback; + fProcessArg = arg; + return 0; + } + } + + int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback, void *arg) + { + if (fThread.GetStatus() == JackThread::kRunning) { + return -1; + } else { + fShutdownCallback = shutdown_callback; + fShutdownArg = arg; + return 0; + } + } + + int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback, void *arg) + { + if (fThread.GetStatus() == JackThread::kRunning) { + return -1; + } else { + fBufferSizeCallback = bufsize_callback; + fBufferSizeArg = arg; + return 0; + } + } + + int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback, void *arg) + { + if (fThread.GetStatus() == JackThread::kRunning) { + return -1; + } else { + fSampleRateCallback = samplerate_callback; + fSampleRateArg = arg; + return 0; + } + } + +}; + +struct JackNetAdapter : public JackAudioAdapterInterface { + + JackNetAdapter(int input, int output, + jack_nframes_t host_buffer_size, + jack_nframes_t host_sample_rate, + jack_nframes_t adapted_buffer_size, + jack_nframes_t adapted_sample_rate) + :JackAudioAdapterInterface(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate) + { + fCaptureChannels = input; + fPlaybackChannels = output; + Create(); + } + + void Create() + { + //ringbuffers + + if (fCaptureChannels > 0) + fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; + if (fPlaybackChannels > 0) + fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; + + if (fAdaptative) { + AdaptRingBufferSize(); + jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize); + } else { + if (fRingbufferCurSize > DEFAULT_RB_SIZE) + fRingbufferCurSize = DEFAULT_RB_SIZE; + jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize); + } + + for (int i = 0; i < fCaptureChannels; i++ ) { + fCaptureRingBuffer[i] = new JackResampler(); + fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); + } + for (int i = 0; i < fPlaybackChannels; i++ ) { + fPlaybackRingBuffer[i] = new JackResampler(); + fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); + } + + if (fCaptureChannels > 0) + jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); + if (fPlaybackChannels > 0) + jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); + } + + virtual ~JackNetAdapter() + { + Destroy(); + } + + void Flush() + { + for (int i = 0; i < fCaptureChannels; i++ ) { + fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); + } + for (int i = 0; i < fPlaybackChannels; i++ ) { + fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); + } + } + +}; + + +} // end of namespace + +using namespace Jack; + +SERVER_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result) +{ + JackNetExtSlave* slave = new JackNetExtSlave(ip, port, name, request); + if (slave->Open(result) == 0) { + return (jack_net_slave_t*)slave; + } else { + delete slave; + return NULL; + } +} + +SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net) +{ + JackNetExtSlave* slave = (JackNetExtSlave*)net; + slave->Close(); + delete slave; + return 0; +} + +SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg) +{ + JackNetExtSlave* slave = (JackNetExtSlave*)net; + return slave->SetProcessCallback(net_callback, arg); +} + +SERVER_EXPORT int jack_net_slave_activate(jack_net_slave_t* net) +{ + JackNetExtSlave* slave = (JackNetExtSlave*)net; + return slave->Start(); +} + +SERVER_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net) +{ + JackNetExtSlave* slave = (JackNetExtSlave*)net; + return slave->Stop(); +} + +SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg) +{ + JackNetExtSlave* slave = (JackNetExtSlave*)net; + return slave->SetBufferSizeCallback(bufsize_callback, arg); +} + +SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg) +{ + JackNetExtSlave* slave = (JackNetExtSlave*)net; + return slave->SetSampleRateCallback(samplerate_callback, arg); +} + +SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg) +{ + JackNetExtSlave* slave = (JackNetExtSlave*)net; + return slave->SetShutdownCallback(shutdown_callback, arg); +} + +// Master API + +SERVER_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result) +{ + JackNetExtMaster* master = new JackNetExtMaster(ip, port, name, request); + if (master->Open(result) == 0) { + return (jack_net_master_t*)master; + } else { + delete master; + return NULL; + } +} + +SERVER_EXPORT int jack_net_master_close(jack_net_master_t* net) +{ + JackNetExtMaster* master = (JackNetExtMaster*)net; + master->Close(); + delete master; + return 0; +} +SERVER_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) +{ + JackNetExtMaster* master = (JackNetExtMaster*)net; + return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer); +} + +SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) +{ + JackNetExtMaster* master = (JackNetExtMaster*)net; + return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer); +} + +// Adapter API + +SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, + jack_nframes_t host_buffer_size, + jack_nframes_t host_sample_rate, + jack_nframes_t adapted_buffer_size, + jack_nframes_t adapted_sample_rate) +{ + return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate); +} + +SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) +{ + delete((JackNetAdapter*)adapter); + return 0; +} + +SERVER_EXPORT void jack_flush_adapter(jack_adapter_t* adapter) +{ + JackNetAdapter* slave = (JackNetAdapter*)adapter; + slave->Flush(); +} + +SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) +{ + JackNetAdapter* slave = (JackNetAdapter*)adapter; + return slave->PushAndPull(input, output, frames); +} + +SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) +{ + JackNetAdapter* slave = (JackNetAdapter*)adapter; + return slave->PullAndPush(input, output, frames); +} + + +#ifdef MY_TARGET_OS_IPHONE + +static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap) +{ + char buffer[300]; + size_t len; + + if (prefix != NULL) { + len = strlen(prefix); + memcpy(buffer, prefix, len); + } else { + len = 0; + } + + vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap); + printf(buffer); + printf("\n"); +} + +SERVER_EXPORT void jack_error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap); + va_end(ap); +} + +SERVER_EXPORT void jack_info(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap); + va_end(ap); +} + +SERVER_EXPORT void jack_log(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap); + va_end(ap); +} + +#else + +// Empty code for now.. + +SERVER_EXPORT void jack_error(const char *fmt, ...) +{} + +SERVER_EXPORT void jack_info(const char *fmt, ...) +{} + +SERVER_EXPORT void jack_log(const char *fmt, ...) +{} + +#endif diff --git a/common/JackNetAdapter.cpp b/common/JackNetAdapter.cpp index b538e833..864ddba4 100644 --- a/common/JackNetAdapter.cpp +++ b/common/JackNetAdapter.cpp @@ -26,7 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. namespace Jack { JackNetAdapter::JackNetAdapter ( jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params ) - : JackAudioAdapterInterface ( buffer_size, sample_rate ), JackNetSlaveInterface(), fThread ( this ) + : JackAudioAdapterInterface ( buffer_size, sample_rate), JackNetSlaveInterface(), fThread ( this ) { jack_log ( "JackNetAdapter::JackNetAdapter" ); @@ -40,8 +40,8 @@ namespace Jack fSocket.GetName ( fParams.fSlaveNetName ); fParams.fMtu = DEFAULT_MTU; fParams.fTransportSync = 0; - fParams.fSendAudioChannels = 2; - fParams.fReturnAudioChannels = 2; + int send_audio = -1; + int return_audio = -1; fParams.fSendMidiChannels = 0; fParams.fReturnMidiChannels = 0; fParams.fSampleRate = sample_rate; @@ -71,10 +71,10 @@ namespace Jack fParams.fMtu = param->value.i; break; case 'C' : - fParams.fSendAudioChannels = param->value.i; + send_audio = param->value.i; break; case 'P' : - fParams.fReturnAudioChannels = param->value.i; + return_audio = param->value.i; break; case 'n' : strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE ); @@ -105,7 +105,13 @@ namespace Jack //set the socket parameters fSocket.SetPort ( port ); fSocket.SetAddress ( fMulticastIP, port ); - + + // If not set, takes deafault + fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio; + + // If not set, takes deafault + fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio; + //set the audio adapter interface channel values SetInputs ( fParams.fSendAudioChannels ); SetOutputs ( fParams.fReturnAudioChannels ); @@ -117,18 +123,18 @@ namespace Jack JackNetAdapter::~JackNetAdapter() { - jack_log ( "JackNetAdapter::~JackNetAdapter" ); + jack_log ("JackNetAdapter::~JackNetAdapter"); int port_index; - if ( fSoftCaptureBuffer ) + if (fSoftCaptureBuffer) { - for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) + for (port_index = 0; port_index < fCaptureChannels; port_index++) delete[] fSoftCaptureBuffer[port_index]; delete[] fSoftCaptureBuffer; } - if ( fSoftPlaybackBuffer ) + if (fSoftPlaybackBuffer) { - for ( port_index = 0; port_index < fPlaybackChannels; port_index++ ) + for ( port_index = 0; port_index < fPlaybackChannels; port_index++) delete[] fSoftPlaybackBuffer[port_index]; delete[] fSoftPlaybackBuffer; } @@ -195,6 +201,8 @@ namespace Jack } //thread------------------------------------------------------------------------------ + // TODO : if failure, thread exist... need to restart ? + bool JackNetAdapter::Init() { jack_log ( "JackNetAdapter::Init" ); @@ -202,24 +210,34 @@ namespace Jack int port_index; //init network connection - if ( !JackNetSlaveInterface::Init() ) + if (!JackNetSlaveInterface::Init()) { + jack_error("JackNetSlaveInterface::Init() error..." ); return false; + } //then set global parameters - SetParams(); + if (!SetParams()) { + jack_error("SetParams error..." ); + return false; + } //set buffers - fSoftCaptureBuffer = new sample_t*[fCaptureChannels]; - for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) - { - fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize]; - fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] ); + if (fCaptureChannels > 0) { + fSoftCaptureBuffer = new sample_t*[fCaptureChannels]; + for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) + { + fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize]; + fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] ); + } } - fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels]; - for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) - { - fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize]; - fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] ); + + if (fPlaybackChannels > 0) { + fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels]; + for ( port_index = 0; port_index < fPlaybackChannels; port_index++ ) + { + fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize]; + fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] ); + } } //set audio adapter parameters diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index 7ccc668f..8bc2ede8 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -149,7 +149,10 @@ namespace Jack } //set global parameters - SetParams(); + if (!SetParams()) { + jack_error("SetParams error..." ); + return false; + } // If -1 at conection time, in/out channels count is sent by the master fCaptureChannels = fParams.fSendAudioChannels; diff --git a/common/JackNetInterface.cpp b/common/JackNetInterface.cpp index f8e5dd5f..afab1d23 100644 --- a/common/JackNetInterface.cpp +++ b/common/JackNetInterface.cpp @@ -24,6 +24,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. using namespace std; +#define PACKET_AVAILABLE_SIZE (fParams.fMtu - sizeof(packet_header_t)) +#define HEADER_SIZE (sizeof(packet_header_t)) + /* TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames, probably also use BUFFER_SIZE_MAX in everything related to MIDI events @@ -36,33 +39,24 @@ namespace Jack JackNetInterface::JackNetInterface() : fSocket() { - fTxBuffer = NULL; - fRxBuffer = NULL; - fNetAudioCaptureBuffer = NULL; - fNetAudioPlaybackBuffer = NULL; - fNetMidiCaptureBuffer = NULL; - fNetMidiPlaybackBuffer = NULL; - memset(&fSendTransportData, 0, sizeof(net_transport_data_t)); - memset(&fReturnTransportData, 0, sizeof(net_transport_data_t)); + Initialize(); } JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port ) { strcpy(fMulticastIP, multicast_ip); - fTxBuffer = NULL; - fRxBuffer = NULL; - fNetAudioCaptureBuffer = NULL; - fNetAudioPlaybackBuffer = NULL; - fNetMidiCaptureBuffer = NULL; - fNetMidiPlaybackBuffer = NULL; - memset(&fSendTransportData, 0, sizeof(net_transport_data_t)); - memset(&fReturnTransportData, 0, sizeof(net_transport_data_t)); + Initialize(); } JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket ) { fParams = params; strcpy(fMulticastIP, multicast_ip); + Initialize(); + } + + void JackNetInterface::Initialize() + { fTxBuffer = NULL; fRxBuffer = NULL; fNetAudioCaptureBuffer = NULL; @@ -73,9 +67,21 @@ namespace Jack memset(&fReturnTransportData, 0, sizeof(net_transport_data_t)); } + void JackNetInterface::FreeNetworkBuffers() + { + delete fNetMidiCaptureBuffer; + delete fNetMidiPlaybackBuffer; + delete fNetAudioCaptureBuffer; + delete fNetAudioPlaybackBuffer; + fNetMidiCaptureBuffer = NULL; + fNetMidiPlaybackBuffer = NULL; + fNetAudioCaptureBuffer = NULL; + fNetAudioPlaybackBuffer = NULL; + } + JackNetInterface::~JackNetInterface() { - jack_log ( "JackNetInterface::~JackNetInterface" ); + jack_log ("JackNetInterface::~JackNetInterface"); fSocket.Close(); delete[] fTxBuffer; @@ -86,91 +92,42 @@ namespace Jack delete fNetMidiPlaybackBuffer; } - void JackNetInterface::SetFramesPerPacket() - { - jack_log ( "JackNetInterface::SetFramesPerPacket" ); - - if (fParams.fSendAudioChannels == 0 && fParams.fReturnAudioChannels == 0) { - fParams.fFramesPerPacket = fParams.fPeriodSize; - } else { - jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ( fParams.fMtu - sizeof ( packet_header_t ) ) - / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) ); - fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period; - } - } - int JackNetInterface::SetNetBufferSize() { - jack_log ( "JackNetInterface::SetNetBufferSize" ); - - float audio_size, midi_size; - int bufsize; //audio - audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket ); + float audio_size = (fNetAudioCaptureBuffer) + ? fNetAudioCaptureBuffer->GetCycleSize() + : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0; + jack_log ("audio_size %f", audio_size); + //midi - midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) * - fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) ); + float midi_size = (fNetMidiCaptureBuffer) + ? fNetMidiCaptureBuffer->GetCycleSize() + : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0; + jack_log ("midi_size %f", midi_size); + //bufsize = sync + audio + midi - bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size); + int bufsize = MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int) midi_size); + jack_log("SetNetBufferSize bufsize = %d", bufsize); //tx buffer - if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) + if (fSocket.SetOption(SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) return SOCKET_ERROR; //rx buffer - if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) + if (fSocket.SetOption(SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) return SOCKET_ERROR; return 0; } - int JackNetInterface::GetNMidiPckt() - { - //even if there is no midi data, jack need an empty buffer to know there is no event to read - //99% of the cases : all data in one packet - if ( fTxHeader.fMidiDataSize <= ( fParams.fMtu - sizeof ( packet_header_t ) ) ) - return 1; - //else, get the number of needed packets (simply slice the biiig buffer) - int npckt = fTxHeader.fMidiDataSize / ( fParams.fMtu - sizeof ( packet_header_t ) ); - if ( fTxHeader.fMidiDataSize % ( fParams.fMtu - sizeof ( packet_header_t ) ) ) - return ++npckt; - return npckt; - } - - bool JackNetInterface::IsNextPacket() + bool JackNetInterface::SetParams() { - packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); - //ignore first cycle - if ( fRxHeader.fCycle <= 1 ) { - return true; - } - //same PcktID (cycle), next SubPcktID (subcycle) - if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) ) { - return true; - } - //next PcktID (cycle), SubPcktID reset to 0 (first subcyle) - if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) ) { - return true; - } - //else, packet(s) missing, return false - return false; - } - - void JackNetInterface::SetParams() - { - //number of audio subcycles (packets) - fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket; - - //payload size - fPayloadSize = fParams.fMtu - sizeof ( packet_header_t ); - //TX header init strcpy ( fTxHeader.fPacketType, "header" ); fTxHeader.fID = fParams.fID; fTxHeader.fCycle = 0; fTxHeader.fSubCycle = 0; - fTxHeader.fMidiDataSize = 0; - fTxHeader.fBitdepth = fParams.fBitdepth; fTxHeader.fIsLastPckt = 0; //RX header init @@ -178,8 +135,6 @@ namespace Jack fRxHeader.fID = fParams.fID; fRxHeader.fCycle = 0; fRxHeader.fSubCycle = 0; - fRxHeader.fMidiDataSize = 0; - fRxHeader.fBitdepth = fParams.fBitdepth; fRxHeader.fIsLastPckt = 0; //network buffers @@ -189,8 +144,10 @@ namespace Jack assert ( fRxBuffer ); //net audio/midi buffers'addresses - fTxData = fTxBuffer + sizeof ( packet_header_t ); - fRxData = fRxBuffer + sizeof ( packet_header_t ); + fTxData = fTxBuffer + HEADER_SIZE; + fRxData = fRxBuffer + HEADER_SIZE; + + return true; } // JackNetMasterInterface ************************************************************************************ @@ -219,11 +176,8 @@ namespace Jack return false; } - //set the number of complete audio frames we can put in a packet - SetFramesPerPacket(); - //send 'SLAVE_SETUP' until 'START_MASTER' received - jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName ); + jack_info ( "Sending parameters to %s...", fParams.fSlaveNetName ); do { session_params_t net_params; @@ -234,8 +188,8 @@ namespace Jack if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR ) jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) ); - memset(&net_params, 0, sizeof ( session_params_t )); - if ( ( ( rx_bytes = fSocket.Recv ( &net_params, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) ) + memset(&net_params, 0, sizeof (session_params_t)); + if (((rx_bytes = fSocket.Recv(&net_params, sizeof(session_params_t), 0)) == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { jack_error ( "Problem with network." ); return false; @@ -249,18 +203,6 @@ namespace Jack return false; } - //set the new timeout for the socket - if ( SetRxTimeout() == SOCKET_ERROR ) { - jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) ); - return false; - } - - //set the new rx buffer size - if ( SetNetBufferSize() == SOCKET_ERROR ) { - jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); - return false; - } - return true; } @@ -269,18 +211,24 @@ namespace Jack jack_log ( "JackNetMasterInterface::SetRxTimeout" ); float time = 0; + //slow or normal mode, short timeout on recv (2 audio subcycles) - if ( ( fParams.fNetworkMode == 's' ) || ( fParams.fNetworkMode == 'n' ) ) - time = 2000000.f * ( static_cast ( fParams.fFramesPerPacket ) / static_cast ( fParams.fSampleRate ) ); + if ((fParams.fNetworkMode == 's') || (fParams.fNetworkMode == 'n')) { + time = 2000000.f * ((fNetAudioCaptureBuffer) + ? fNetAudioCaptureBuffer->GetCycleDuration() + : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleDuration() : 0); + } //fast mode, wait for 75% of the entire cycle duration - else if ( fParams.fNetworkMode == 'f' ) - time = 750000.f * ( static_cast ( fParams.fPeriodSize ) / static_cast ( fParams.fSampleRate ) ); - return fSocket.SetTimeOut ( static_cast ( time ) ); + else if (fParams.fNetworkMode == 'f') { + time = 750000.f * (static_cast(fParams.fPeriodSize) / static_cast(fParams.fSampleRate)); + } + + return fSocket.SetTimeOut (static_cast(time)); } - void JackNetMasterInterface::SetParams() + bool JackNetMasterInterface::SetParams() { - jack_log ( "JackNetMasterInterface::SetParams" ); + jack_log("JackNetMasterInterface::SetParams"); JackNetInterface::SetParams(); @@ -288,20 +236,77 @@ namespace Jack fRxHeader.fDataStream = 'r'; //midi net buffers - fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData ); - fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData ); - assert ( fNetMidiCaptureBuffer ); - assert ( fNetMidiPlaybackBuffer ); + if (fParams.fSendMidiChannels) + fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fTxData); + + if (fParams.fReturnMidiChannels) + fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fRxData); + + try { + + //audio net buffers + if (fParams.fSendAudioChannels) { + + switch (fParams.fSampleEncoder) { + + case JackFloatEncoder: + fNetAudioCaptureBuffer = new NetFloatAudioBuffer(&fParams, fParams.fSendAudioChannels, fTxData); + break; + + case JackIntEncoder: + fNetAudioCaptureBuffer = new NetIntAudioBuffer(&fParams, fParams.fSendAudioChannels, fTxData); + break; + + case JackCeltEncoder: + #ifdef CELT + fNetAudioCaptureBuffer = new NetCeltAudioBuffer(&fParams, fParams.fSendAudioChannels, fTxData, fParams.fKBps); + #endif + break; + } + } + + if (fParams.fReturnAudioChannels) { + + switch (fParams.fSampleEncoder) { + + case JackFloatEncoder: + fNetAudioPlaybackBuffer = new NetFloatAudioBuffer(&fParams, fParams.fReturnAudioChannels, fRxData); + break; + + case JackIntEncoder: + fNetAudioPlaybackBuffer = new NetIntAudioBuffer(&fParams, fParams.fReturnAudioChannels, fRxData); + break; + + case JackCeltEncoder: + #ifdef CELT + fNetAudioPlaybackBuffer = new NetCeltAudioBuffer(&fParams, fParams.fReturnAudioChannels, fRxData, fParams.fKBps); + #endif + break; + } + } + + } catch (exception&) { + jack_error("NetAudioBuffer allocation error..."); + return false; + } - //audio net buffers - fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData ); - fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData ); - assert ( fNetAudioCaptureBuffer ); - assert ( fNetAudioPlaybackBuffer ); + //set the new timeout for the socket + if (SetRxTimeout() == SOCKET_ERROR) { + jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE)); + goto error; + } - //audio netbuffer length - fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize(); - fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize(); + //set the new rx buffer size + if (SetNetBufferSize() == SOCKET_ERROR) { + jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); + goto error; + } + + return true; + + error: + FreeNetworkBuffers(); + return false; } void JackNetMasterInterface::Exit() @@ -328,27 +333,26 @@ namespace Jack mcast_socket.Close(); } - int JackNetMasterInterface::Recv ( size_t size, int flags ) + int JackNetMasterInterface::Recv(size_t size, int flags) { int rx_bytes; - if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning ) - { + + if ((( rx_bytes = fSocket.Recv(fRxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) { net_error_t error = fSocket.GetError(); - //no data isn't really a network error, so just return 0 avalaible read bytes - if ( error == NET_NO_DATA ) + //no data isn't really a network error, so just return 0 available read bytes + if (error == NET_NO_DATA) { return 0; - else if ( error == NET_CONN_ERROR ) - { + } else if (error == NET_CONN_ERROR) { //fatal connection issue, exit - jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) ); + jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError(NET_ERROR_CODE)); //ask to the manager to properly remove the master Exit(); // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. ThreadExit(); + } else { + jack_error ( "Error in master receive : %s", StrError(NET_ERROR_CODE)); } - else - jack_error ( "Error in master receive : %s", StrError ( NET_ERROR_CODE ) ); } packet_header_t* header = reinterpret_cast(fRxBuffer); @@ -356,26 +360,24 @@ namespace Jack return rx_bytes; } - int JackNetMasterInterface::Send ( size_t size, int flags ) + int JackNetMasterInterface::Send(size_t size, int flags) { int tx_bytes; packet_header_t* header = reinterpret_cast(fTxBuffer); PacketHeaderHToN(header, header); - if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning ) - { + if (((tx_bytes = fSocket.Send(fTxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) { net_error_t error = fSocket.GetError(); - if ( error == NET_CONN_ERROR ) - { + if (error == NET_CONN_ERROR) { //fatal connection issue, exit - jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) ); + jack_error ("'%s' : %s, exiting.", fParams.fName, StrError (NET_ERROR_CODE)); Exit(); // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. ThreadExit(); + } else { + jack_error("Error in master send : %s", StrError(NET_ERROR_CODE)); } - else - jack_error ( "Error in master send : %s", StrError ( NET_ERROR_CODE ) ); } return tx_bytes; } @@ -383,7 +385,7 @@ namespace Jack bool JackNetMasterInterface::IsSynched() { if (fParams.fNetworkMode == 's') { - return (fCycleOffset < 3); + return (fCycleOffset < (CYCLE_OFFSET_SLOW + 1)); } else { return true; } @@ -394,47 +396,51 @@ namespace Jack fTxHeader.fCycle++; fTxHeader.fSubCycle = 0; fTxHeader.fDataType = 's'; - fTxHeader.fIsLastPckt = ( fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ? 1 : 0; - fTxHeader.fPacketSize = fParams.fMtu; - memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) ); - return Send ( fTxHeader.fPacketSize, 0 ); + fTxHeader.fIsLastPckt = (fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE; + + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + return Send(fTxHeader.fPacketSize, 0); } int JackNetMasterInterface::DataSend() { uint subproc; + uint data_size; + //midi - if ( fParams.fSendMidiChannels > 0) + if (fParams.fSendMidiChannels > 0) { //set global header fields and get the number of midi packets fTxHeader.fDataType = 'm'; - fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts(); - fTxHeader.fNMidiPckt = GetNMidiPckt(); - for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ ) + data_size = fNetMidiCaptureBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetMidiCaptureBuffer->GetNumPackets(); + + for ( subproc = 0; subproc < fTxHeader.fNumPacket; subproc++ ) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && (fParams.fSendAudioChannels == 0)) ? 1 : 0; - fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize ); - memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) ); - if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR ) + fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && (fParams.fSendAudioChannels == 0)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiCaptureBuffer->RenderToNetwork(subproc, data_size); + memcpy ( fTxBuffer, &fTxHeader, HEADER_SIZE); + if (Send (fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } } //audio - if ( fParams.fSendAudioChannels > 0) + if (fParams.fSendAudioChannels > 0) { fTxHeader.fDataType = 'a'; - fTxHeader.fMidiDataSize = 0; - fTxHeader.fNMidiPckt = 0; - for ( subproc = 0; subproc < fNSubProcess; subproc++ ) + data_size = fNetAudioCaptureBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetAudioCaptureBuffer->GetNumPackets(); + + for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0; - fTxHeader.fPacketSize = fAudioTxLen; - memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) ); - fNetAudioCaptureBuffer->RenderFromJackPorts ( subproc ); - if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR ) + fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioCaptureBuffer->RenderToNetwork(subproc, data_size); + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } } @@ -445,7 +451,7 @@ namespace Jack int JackNetMasterInterface::SyncRecv() { packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); - int rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); + int rx_bytes = Recv(HEADER_SIZE, MSG_PEEK); if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) ) return rx_bytes; @@ -460,14 +466,20 @@ namespace Jack // - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master // - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process) - if (fCycleOffset < 2) - return 0; - else - rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - if (fCycleOffset > 2) { + /* + if (fCycleOffset < CYCLE_OFFSET_SLOW) { + return 0; + } else { + rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + } + */ + + rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + + if (fCycleOffset != fLastfCycleOffset) jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); - } + fLastfCycleOffset = fCycleOffset; break; case 'n' : @@ -475,13 +487,15 @@ namespace Jack // - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth // - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter // - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it - if (fCycleOffset < 1) + if (fCycleOffset < CYCLE_OFFSET_NORMAL) { return 0; - else + } else { rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + } - if (fCycleOffset != 1) + if (fCycleOffset > CYCLE_OFFSET_NORMAL) { jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); + } break; case 'f' : @@ -491,8 +505,10 @@ namespace Jack // - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - if (fCycleOffset != 0) + if (fCycleOffset > CYCLE_OFFSET_FAST) { jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); + } + break; break; } @@ -503,65 +519,55 @@ namespace Jack int JackNetMasterInterface::DataRecv() { int rx_bytes = 0; - uint jumpcnt = 0; uint recvd_midi_pckt = 0; uint recvd_audio_pckt = 0; + packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); while ( !fRxHeader.fIsLastPckt ) { //how much data is queued on the rx buffer ? - rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); + rx_bytes = Recv(HEADER_SIZE, MSG_PEEK); + //error here, problem with recv, just skip the cycle (return -1) if ( rx_bytes == SOCKET_ERROR ) return rx_bytes; - //if no data - if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) ) - { - jack_error ( "No data from %s...", fParams.fName ); - jumpcnt = 0; - } - //else if data is valid, + if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) ) { //read data switch ( rx_head->fDataType ) { case 'm': //midi - rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) ); - if ( ++recvd_midi_pckt == rx_head->fNMidiPckt ) + fNetMidiPlaybackBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + // Last midi packet is received, so finish rendering... + if (++recvd_midi_pckt == rx_head->fNumPacket) fNetMidiPlaybackBuffer->RenderToJackPorts(); - jumpcnt = 0; break; case 'a': //audio - rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - // SL: 25/01/09 - // if ( !IsNextPacket() ) - // jack_error ( "Packet(s) missing from '%s'...", fParams.fName ); - if (recvd_audio_pckt++ != rx_head->fSubCycle) { - jack_error("Packet(s) missing from '%s'...", fParams.fSlaveNetName); - } + rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fSubCycle = rx_head->fSubCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle ); - jumpcnt = 0; + fNetAudioPlaybackBuffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + // Last audio packet is received, so finish rendering... + if (fRxHeader.fIsLastPckt) + fNetAudioPlaybackBuffer->RenderToJackPorts(); break; case 's': //sync - /* SL: 25/01/09 - if ( rx_head->fCycle == fTxHeader.fCycle ) - return 0; - */ jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); + // TODO : finish midi and audio rendering ? + fNetAudioPlaybackBuffer->RenderToJackPorts(); return 0; } } } + return rx_bytes; } @@ -569,7 +575,7 @@ namespace Jack { //this method contains every step of sync packet informations coding //first of all, reset sync packet - memset ( fTxData, 0, fPayloadSize ); + memset ( fTxData, 0, PACKET_AVAILABLE_SIZE ); //then, first step : transport if (fParams.fTransportSync) { @@ -634,10 +640,10 @@ namespace Jack } // Separate the connection protocol into two separated step - - bool JackNetSlaveInterface::InitConnection() + bool JackNetSlaveInterface::InitConnection(int time_out) { - jack_log ( "JackNetSlaveInterface::InitConnection()" ); + jack_log("JackNetSlaveInterface::InitConnection()"); + int try_count = (time_out > 0) ? ((1000000 * time_out) / SLAVE_INIT_TIMEOUT) : LONG_MAX; //set the parameters to send strcpy (fParams.fPacketType, "params"); @@ -648,13 +654,13 @@ namespace Jack do { //get a master - status = SendAvailableToMaster(); + status = SendAvailableToMaster(try_count); if (status == NET_SOCKET_ERROR) return false; } - while (status != NET_CONNECTED); + while (status != NET_CONNECTED && --try_count > 0); - return true; + return (try_count != 0); } bool JackNetSlaveInterface::InitRendering() @@ -675,7 +681,7 @@ namespace Jack return true; } - net_status_t JackNetSlaveInterface::SendAvailableToMaster() + net_status_t JackNetSlaveInterface::SendAvailableToMaster(long try_count) { jack_log ( "JackNetSlaveInterface::SendAvailableToMaster()" ); //utility @@ -723,44 +729,44 @@ namespace Jack return NET_RECV_ERROR; } } - while ( strcmp ( host_params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &host_params ) != SLAVE_SETUP ) ); + while (strcmp(host_params.fPacketType, fParams.fPacketType) && (GetPacketType(&host_params) != SLAVE_SETUP) && (--try_count > 0)); + + // Time out failure.. + if (try_count == 0) { + jack_error("Time out error in connect"); + return NET_CONNECT_ERROR; + } //everything is OK, copy parameters + SessionParamsDisplay(&host_params); fParams = host_params; - //set the new buffer sizes - if ( SetNetBufferSize() == SOCKET_ERROR ) { - jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); - return NET_SOCKET_ERROR; - } - //connect the socket - if ( fSocket.Connect() == SOCKET_ERROR ) { - jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) ); + if (fSocket.Connect() == SOCKET_ERROR) { + jack_error("Error in connect : %s", StrError(NET_ERROR_CODE)); return NET_CONNECT_ERROR; } - return NET_CONNECTED; } net_status_t JackNetSlaveInterface::SendStartToMaster() { - jack_log ( "JackNetSlaveInterface::SendStartToMaster" ); + jack_log("JackNetSlaveInterface::SendStartToMaster"); //tell the master to start session_params_t net_params; memset(&net_params, 0, sizeof ( session_params_t )); SetPacketType ( &fParams, START_MASTER ); SessionParamsHToN(&fParams, &net_params); - if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR ) + if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR) { - jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) ); - return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR; + jack_error("Error in send : %s", StrError(NET_ERROR_CODE)); + return (fSocket.GetError() == NET_CONN_ERROR) ? NET_ERROR : NET_SEND_ERROR; } return NET_ROLLING; } - void JackNetSlaveInterface::SetParams() + bool JackNetSlaveInterface::SetParams() { jack_log("JackNetSlaveInterface::SetParams"); @@ -769,37 +775,91 @@ namespace Jack fTxHeader.fDataStream = 'r'; fRxHeader.fDataStream = 's'; - //midi net buffers - fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData ); - fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData ); + //midi net buffers + if (fParams.fSendMidiChannels) + fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fTxData); + + if (fParams.fReturnMidiChannels) + fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fRxData); + + try { + + //audio net buffers + if (fParams.fSendAudioChannels) { - //audio net buffers - fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData ); - fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData ); + switch (fParams.fSampleEncoder) { - //audio netbuffer length - fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize(); - fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize(); + case JackFloatEncoder: + fNetAudioCaptureBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData ); + break; + + case JackIntEncoder: + fNetAudioCaptureBuffer = new NetIntAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData ); + break; + + case JackCeltEncoder: + #ifdef CELT + fNetAudioCaptureBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData, fParams.fKBps ); + #endif + break; + } + } + + if (fParams.fReturnAudioChannels) { + + switch (fParams.fSampleEncoder) { + + case JackFloatEncoder: + fNetAudioPlaybackBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData ); + break; + + case JackIntEncoder: + fNetAudioPlaybackBuffer = new NetIntAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData); + break; + + case JackCeltEncoder: + #ifdef CELT + fNetAudioPlaybackBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData, fParams.fKBps ); + #endif + break; + } + } + + } catch (exception&) { + jack_error("NetAudioBuffer allocation error..."); + return false; + } + + //set the new buffer sizes + if ( SetNetBufferSize() == SOCKET_ERROR ) { + jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); + goto error; + } + + return true; + + error: + FreeNetworkBuffers(); + return false; } - int JackNetSlaveInterface::Recv ( size_t size, int flags ) + int JackNetSlaveInterface::Recv(size_t size, int flags) { - int rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ); + int rx_bytes = fSocket.Recv(fRxBuffer, size, flags); //handle errors if ( rx_bytes == SOCKET_ERROR ) { net_error_t error = fSocket.GetError(); //no data isn't really an error in realtime processing, so just return 0 - if ( error == NET_NO_DATA ) + if ( error == NET_NO_DATA ) { jack_error ( "No data, is the master still running ?" ); //if a network error occurs, this exception will restart the driver - else if ( error == NET_CONN_ERROR ) - { + } else if ( error == NET_CONN_ERROR ) { jack_error ( "Connection lost." ); throw JackNetException(); - } - else + } else { jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) ); + } } packet_header_t* header = reinterpret_cast(fRxBuffer); @@ -807,7 +867,7 @@ namespace Jack return rx_bytes; } - int JackNetSlaveInterface::Send ( size_t size, int flags ) + int JackNetSlaveInterface::Send(size_t size, int flags) { packet_header_t* header = reinterpret_cast(fTxBuffer); PacketHeaderHToN(header, header); @@ -818,13 +878,12 @@ namespace Jack { net_error_t error = fSocket.GetError(); //if a network error occurs, this exception will restart the driver - if ( error == NET_CONN_ERROR ) - { + if ( error == NET_CONN_ERROR ) { jack_error ( "Connection lost." ); throw JackNetException(); - } - else + } else { jack_error ( "Fatal error in slave send : %s", StrError ( NET_ERROR_CODE ) ); + } } return tx_bytes; } @@ -833,10 +892,11 @@ namespace Jack { int rx_bytes = 0; packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); + //receive sync (launch the cycle) do { - rx_bytes = Recv ( fParams.fMtu, 0 ); + rx_bytes = Recv(HEADER_SIZE, 0); //connection issue, send will detect it, so don't skip the cycle (return 0) if ( rx_bytes == SOCKET_ERROR ) return rx_bytes; @@ -849,51 +909,55 @@ namespace Jack int JackNetSlaveInterface::DataRecv() { + int rx_bytes = 0; uint recvd_midi_pckt = 0; uint recvd_audio_pckt = 0; - int rx_bytes = 0; + packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); while ( !fRxHeader.fIsLastPckt ) { - rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); - //error here, problem with recv, just skip the cycle (return -1) + //how much data is queued on the rx buffer ? + rx_bytes = Recv(HEADER_SIZE, MSG_PEEK); + //error here, problem with recv, just skip the cycle (return -1) if ( rx_bytes == SOCKET_ERROR ) return rx_bytes; + if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) ) { switch ( rx_head->fDataType ) { case 'm': //midi - rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) ); - if ( ++recvd_midi_pckt == rx_head->fNMidiPckt ) + fNetMidiCaptureBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + // Last midi packet is received, so finish rendering... + if (++recvd_midi_pckt == rx_head->fNumPacket) fNetMidiCaptureBuffer->RenderToJackPorts(); break; case 'a': //audio - rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - //SL: 25/01/09 - // if ( !IsNextPacket() ) - // jack_error ( "Packet(s) missing..." ); - if (recvd_audio_pckt++ != rx_head->fSubCycle) { - jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName); - } + rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fSubCycle = rx_head->fSubCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle ); + fNetAudioCaptureBuffer->RenderFromNetwork (rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + // Last audio packet is received, so finish rendering... + if (fRxHeader.fIsLastPckt) + fNetAudioCaptureBuffer->RenderToJackPorts(); break; case 's': //sync jack_info ( "NetSlave : overloaded, skipping receive." ); + // TODO : finish midi and audio rendering ? + fNetAudioCaptureBuffer->RenderToJackPorts(); return 0; } } } + fRxHeader.fCycle = rx_head->fCycle; return 0; } @@ -901,35 +965,39 @@ namespace Jack int JackNetSlaveInterface::SyncSend() { //tx header - if ( fParams.fSlaveSyncMode ) + if ( fParams.fSlaveSyncMode ) { fTxHeader.fCycle = fRxHeader.fCycle; - else + } else { fTxHeader.fCycle++; + } fTxHeader.fSubCycle = 0; fTxHeader.fDataType = 's'; - fTxHeader.fIsLastPckt = ( fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ? 1 : 0; - fTxHeader.fPacketSize = fParams.fMtu; - memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) ); - return Send ( fTxHeader.fPacketSize, 0 ); + fTxHeader.fIsLastPckt = (fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE; + + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + return Send (fTxHeader.fPacketSize, 0); } int JackNetSlaveInterface::DataSend() { uint subproc; + uint data_size; //midi - if ( fParams.fReturnMidiChannels > 0) + if (fParams.fReturnMidiChannels > 0) { + //set global header fields and get the number of midi packets fTxHeader.fDataType = 'm'; - fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts(); - fTxHeader.fNMidiPckt = GetNMidiPckt(); - for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ ) + data_size = fNetMidiPlaybackBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetMidiPlaybackBuffer->GetNumPackets(); + for ( subproc = 0; subproc < fTxHeader.fNumPacket; subproc++ ) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels ) ? 1 : 0; - fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize ); - memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) ); - if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR ) + fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && !fParams.fReturnAudioChannels) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiPlaybackBuffer->RenderToNetwork(subproc, data_size); + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } } @@ -938,16 +1006,15 @@ namespace Jack if ( fParams.fReturnAudioChannels > 0) { fTxHeader.fDataType = 'a'; - fTxHeader.fMidiDataSize = 0; - fTxHeader.fNMidiPckt = 0; - for ( subproc = 0; subproc < fNSubProcess; subproc++ ) + data_size = fNetAudioPlaybackBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetAudioPlaybackBuffer->GetNumPackets(); + for ( subproc = 0; subproc < fTxHeader.fNumPacket; subproc++ ) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0; - fTxHeader.fPacketSize = fAudioTxLen; - memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) ); - fNetAudioPlaybackBuffer->RenderFromJackPorts ( subproc ); - if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR ) + fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioPlaybackBuffer->RenderToNetwork(subproc, data_size); + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } } @@ -959,7 +1026,7 @@ namespace Jack { //this method contains every step of sync packet informations coding //first of all, reset sync packet - memset ( fTxData, 0, fPayloadSize ); + memset ( fTxData, 0, PACKET_AVAILABLE_SIZE ); //then first step : transport if (fParams.fTransportSync) { EncodeTransportData(); diff --git a/common/JackNetInterface.h b/common/JackNetInterface.h index 64e8f40e..c417e7f2 100644 --- a/common/JackNetInterface.h +++ b/common/JackNetInterface.h @@ -34,10 +34,11 @@ namespace Jack protected: + void Initialize(); + session_params_t fParams; JackNetSocket fSocket; char fMulticastIP[32]; - uint fNSubProcess; //headers packet_header_t fTxHeader; @@ -59,19 +60,12 @@ namespace Jack NetAudioBuffer* fNetAudioCaptureBuffer; NetAudioBuffer* fNetAudioPlaybackBuffer; - //sizes - int fAudioRxLen; - int fAudioTxLen; - int fPayloadSize; - //utility methods - void SetFramesPerPacket(); int SetNetBufferSize(); - int GetNMidiPckt(); - bool IsNextPacket(); + void FreeNetworkBuffers(); //virtual methods : depends on the sub class master/slave - virtual void SetParams(); + virtual bool SetParams(); virtual bool Init() = 0; //transport @@ -111,10 +105,11 @@ namespace Jack bool fRunning; int fCycleOffset; + int fLastfCycleOffset; bool Init(); int SetRxTimeout(); - void SetParams(); + bool SetParams(); void Exit(); @@ -134,8 +129,7 @@ namespace Jack bool IsSynched(); public: - - JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCycleOffset(0) + JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCycleOffset(0), fLastfCycleOffset(0) {} JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : JackNetInterface ( params, socket, multicast_ip ) @@ -156,13 +150,13 @@ namespace Jack static uint fSlaveCounter; bool Init(); - bool InitConnection(); + bool InitConnection(int time_out); bool InitRendering(); - net_status_t SendAvailableToMaster(); + net_status_t SendAvailableToMaster(long count = LONG_MAX); // long here (and not int...) net_status_t SendStartToMaster(); - void SetParams(); + bool SetParams(); int SyncRecv(); int SyncSend(); @@ -221,8 +215,11 @@ namespace Jack #define SLAVE_SETUP_RETRY 5 #define MASTER_INIT_TIMEOUT 1000000 // in usec -#define SLAVE_INIT_TIMEOUT 2000000 // in usec +#define SLAVE_INIT_TIMEOUT 1000000 // in usec -#define MAX_LATENCY 6 +#define CYCLE_OFFSET_FAST 0 +#define CYCLE_OFFSET_NORMAL 1 +#define CYCLE_OFFSET_SLOW 30 +#define MAX_LATENCY CYCLE_OFFSET_SLOW * 4 #endif diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index 25619d07..2be6a9f7 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -113,11 +113,16 @@ namespace Jack bool JackNetMaster::Init(bool auto_connect) { //network init - if ( !JackNetMasterInterface::Init() ) + if (!JackNetMasterInterface::Init()){ + jack_error("JackNetMasterInterface::Init() error..." ); return false; + } //set global parameters - SetParams(); + if (!SetParams()) { + jack_error("SetParams error..." ); + return false; + } //jack client and process jack_status_t status; @@ -205,7 +210,6 @@ namespace Jack } } - //midi for ( i = 0; i < fParams.fSendMidiChannels; i++ ) { @@ -626,8 +630,6 @@ namespace Jack if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR ) jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) ); - jack_info ( "Waiting for a slave..." ); - //main loop, wait for data, deal with it and wait again do { @@ -681,7 +683,6 @@ namespace Jack params.fID = ++fGlobalID; params.fSampleRate = jack_get_sample_rate ( fManagerClient ); params.fPeriodSize = jack_get_buffer_size ( fManagerClient ); - params.fBitdepth = 0; if (params.fSendAudioChannels == -1) { params.fSendAudioChannels = CountIO(JackPortIsPhysical | JackPortIsOutput); diff --git a/common/JackNetTool.cpp b/common/JackNetTool.cpp index 82aa01ad..ac08cb92 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -19,6 +19,69 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackNetTool.h" +#ifdef __APPLE__ + +#include + +class HardwareClock +{ +public: + HardwareClock(); + + void Reset(); + void Update(); + + float GetDeltaTime() const; + double GetTime() const; + +private: + double m_clockToSeconds; + + uint64_t m_startAbsTime; + uint64_t m_lastAbsTime; + + double m_time; + float m_deltaTime; +}; + +HardwareClock::HardwareClock() +{ + mach_timebase_info_data_t info; + mach_timebase_info(&info); + m_clockToSeconds = (double)info.numer/info.denom/1000000000.0; + Reset(); +} + +void HardwareClock::Reset() +{ + m_startAbsTime = mach_absolute_time(); + m_lastAbsTime = m_startAbsTime; + m_time = m_startAbsTime*m_clockToSeconds; + m_deltaTime = 1.0f/60.0f; +} + +void HardwareClock::Update() +{ + const uint64_t currentTime = mach_absolute_time(); + const uint64_t dt = currentTime - m_lastAbsTime; + + m_time = currentTime*m_clockToSeconds; + m_deltaTime = (double)dt*m_clockToSeconds; + m_lastAbsTime = currentTime; +} + +float HardwareClock::GetDeltaTime() const +{ + return m_deltaTime; +} + +double HardwareClock::GetTime() const +{ + return m_time; +} + +#endif + using namespace std; namespace Jack @@ -35,6 +98,9 @@ namespace Jack for ( int port_index = 0; port_index < fNPorts; port_index++ ) fPortBuffer[port_index] = NULL; fNetBuffer = net_buffer; + + fCycleSize = params->fMtu * (max(params->fSendMidiChannels, params->fReturnMidiChannels) * + params->fPeriodSize * sizeof(sample_t) / (params->fMtu - sizeof(packet_header_t))); } NetMidiBuffer::~NetMidiBuffer() @@ -43,9 +109,21 @@ namespace Jack delete[] fPortBuffer; } - size_t NetMidiBuffer::GetSize() + size_t NetMidiBuffer::GetCycleSize() { - return fMaxBufsize; + return fCycleSize; + } + + int NetMidiBuffer::GetNumPackets() + { + /* + return (data_size % PACKET_AVAILABLE_SIZE) + ? (data_size / PACKET_AVAILABLE_SIZE + 1) + : data_size / PACKET_AVAILABLE_SIZE; + */ + + //TODO + return 0; } void NetMidiBuffer::SetBuffer ( int index, JackMidiBuffer* buffer ) @@ -119,103 +197,443 @@ namespace Jack int NetMidiBuffer::RenderToNetwork ( int subcycle, size_t total_size ) { int size = total_size - subcycle * fMaxPcktSize; - int copy_size = ( size <= fMaxPcktSize ) ? size : fMaxPcktSize; - memcpy ( fNetBuffer, fBuffer + subcycle * fMaxPcktSize, copy_size ); + int copy_size = (size <= fMaxPcktSize) ? size : fMaxPcktSize; + memcpy(fNetBuffer, fBuffer + subcycle * fMaxPcktSize, copy_size); return copy_size; } - // net audio buffer ********************************************************************************* - NetAudioBuffer::NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) + NetFloatAudioBuffer::NetFloatAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) + : fPortBuffer(params, nports), fNetBuffer(net_buffer) + {} + + NetFloatAudioBuffer::~NetFloatAudioBuffer() + {} + + size_t NetFloatAudioBuffer::GetCycleSize() + { + return fPortBuffer.GetCycleSize(); + } + + void NetFloatAudioBuffer::SetBuffer ( int index, sample_t* buffer ) + { + fPortBuffer.SetBuffer(index, buffer); + } + + sample_t* NetFloatAudioBuffer::GetBuffer ( int index ) + { + return fPortBuffer.GetBuffer(index); + } + + int NetFloatAudioBuffer::RenderFromJackPorts () + { + return fPortBuffer.RenderFromJackPorts(); + } + + int NetFloatAudioBuffer::RenderToJackPorts () + { + return fPortBuffer.RenderToJackPorts(); + } + + //network<->buffer + int NetFloatAudioBuffer::RenderFromNetwork ( int cycle, int subcycle, size_t copy_size ) + { + return fPortBuffer.RenderFromNetwork(fNetBuffer, cycle, subcycle, copy_size); + } + + int NetFloatAudioBuffer::RenderToNetwork (int subcycle, size_t total_size ) { + return fPortBuffer.RenderToNetwork(fNetBuffer, subcycle, total_size); + } + + // Celt audio buffer ********************************************************************************* + +#ifdef CELT + + #define KPS 32 + #define KPS_DIV 8 + + NetCeltAudioBuffer::NetCeltAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer, int kbps ) + : fNetBuffer(net_buffer) + { + int res1, res2; + fNPorts = nports; fPeriodSize = params->fPeriodSize; - fSubPeriodSize = params->fFramesPerPacket; - fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); + + fCeltMode = new CELTMode *[fNPorts]; + fCeltEncoder = new CELTEncoder *[fNPorts]; + fCeltDecoder = new CELTDecoder *[fNPorts]; + + memset(fCeltMode, 0, fNPorts * sizeof(CELTMode*)); + memset(fCeltEncoder, 0, fNPorts * sizeof(CELTEncoder*)); + memset(fCeltDecoder, 0, fNPorts * sizeof(CELTDecoder*)); + + int error = CELT_OK; + + for (int i = 0; i < fNPorts; i++) { + fCeltMode[i] = celt_mode_create(params->fSampleRate, params->fPeriodSize, &error); + if (error != CELT_OK) + goto error; + + fCeltEncoder[i] = celt_encoder_create(fCeltMode[i], 1, &error); + if (error != CELT_OK) + goto error; + celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1)); + + fCeltDecoder[i] = celt_decoder_create(fCeltMode[i], 1, &error); + if (error != CELT_OK) + goto error; + celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1)); + } + fPortBuffer = new sample_t* [fNPorts]; - for ( int port_index = 0; port_index < fNPorts; port_index++ ) + for (int port_index = 0; port_index < fNPorts; port_index++) fPortBuffer[port_index] = NULL; - fNetBuffer = net_buffer; + + /* + celt_int32 lookahead; + celt_mode_info( celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); + */ + + fCompressedSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8); + //fCompressedSizeByte = (params->fPeriodSize * sizeof(sample_t)) / KPS_DIV; // TODO + + fCompressedBuffer = new unsigned char* [fNPorts]; + for (int port_index = 0; port_index < fNPorts; port_index++) + fCompressedBuffer[port_index] = new unsigned char[fCompressedSizeByte]; + + jack_log("NetCeltAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte); + + res1 = (fNPorts * fCompressedSizeByte) % (params->fMtu - sizeof(packet_header_t)); + res2 = (fNPorts * fCompressedSizeByte) / (params->fMtu - sizeof(packet_header_t)); + + jack_log("NetCeltAudioBuffer res1 = %d res2 = %d", res1, res2); + + fNumPackets = (res1) ? (res2 + 1) : res2; + + fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets; + fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets; + + jack_log("NetCeltAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); + + fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate); + fCycleSize = params->fMtu * fNumPackets; + + fLastSubCycle = -1; + return; + + error: + + FreeCelt(); + throw std::bad_alloc(); } - NetAudioBuffer::~NetAudioBuffer() + NetCeltAudioBuffer::~NetCeltAudioBuffer() { - delete[] fPortBuffer; + FreeCelt(); + + for (int port_index = 0; port_index < fNPorts; port_index++) + delete [] fCompressedBuffer[port_index]; + + delete [] fCompressedBuffer; + delete [] fPortBuffer; } - size_t NetAudioBuffer::GetSize() + void NetCeltAudioBuffer::FreeCelt() { - return fNPorts * fSubPeriodBytesSize; + for (int i = 0; i < fNPorts; i++) { + if (fCeltEncoder[i]) + celt_encoder_destroy(fCeltEncoder[i]); + if (fCeltDecoder[i]) + celt_decoder_destroy(fCeltDecoder[i]); + if (fCeltMode[i]) + celt_mode_destroy(fCeltMode[i]); + } + + delete [] fCeltMode; + delete [] fCeltEncoder; + delete [] fCeltDecoder; } - void NetAudioBuffer::SetBuffer ( int index, sample_t* buffer ) + size_t NetCeltAudioBuffer::GetCycleSize() + { + return fCycleSize; + } + + float NetCeltAudioBuffer::GetCycleDuration() + { + return fCycleDuration; + } + + int NetCeltAudioBuffer::GetNumPackets() + { + return fNumPackets; + } + + void NetCeltAudioBuffer::SetBuffer(int index, sample_t* buffer) { assert(fPortBuffer); fPortBuffer[index] = buffer; } - sample_t* NetAudioBuffer::GetBuffer ( int index ) + sample_t* NetCeltAudioBuffer::GetBuffer(int index) { assert(fPortBuffer); return fPortBuffer[index]; } -#ifdef __BIG_ENDIAN__ - - static inline jack_default_audio_sample_t SwapFloat(jack_default_audio_sample_t f) + int NetCeltAudioBuffer::RenderFromJackPorts() { - union - { - jack_default_audio_sample_t f; - unsigned char b[4]; - } dat1, dat2; + float floatbuf[fPeriodSize]; - dat1.f = f; - dat2.b[0] = dat1.b[3]; - dat2.b[1] = dat1.b[2]; - dat2.b[2] = dat1.b[1]; - dat2.b[3] = dat1.b[0]; - return dat2.f; + for (int port_index = 0; port_index < fNPorts; port_index++) { + memcpy(floatbuf, fPortBuffer[port_index], fPeriodSize * sizeof(float)); + int res = celt_encode_float(fCeltEncoder[port_index], floatbuf, NULL, fCompressedBuffer[port_index], fCompressedSizeByte); + if (res != fCompressedSizeByte) { + jack_error("celt_encode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res); + } + } + + return fNPorts * fCompressedSizeByte; // in bytes } - void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) + int NetCeltAudioBuffer::RenderToJackPorts() { - for ( int port_index = 0; port_index < fNPorts; port_index++ ) { - jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); - jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(fNetBuffer + port_index * fSubPeriodBytesSize); - for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(jack_default_audio_sample_t); sample++) { - dst[sample] = SwapFloat(src[sample]); + for (int port_index = 0; port_index < fNPorts; port_index++) { + int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index]); + if (res != CELT_OK) { + jack_error("celt_decode_float error res = %d", fCompressedSizeByte, res); } } + + fLastSubCycle = -1; + //return fPeriodSize * sizeof(sample_t); // in bytes; TODO + return 0; } - void NetAudioBuffer::RenderToJackPorts ( int subcycle ) + //network<->buffer + int NetCeltAudioBuffer::RenderFromNetwork(int cycle, int subcycle, size_t copy_size) { - for ( int port_index = 0; port_index < fNPorts; port_index++ ) { - jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(fNetBuffer + port_index * fSubPeriodBytesSize); - jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); - for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(jack_default_audio_sample_t); sample++) { - dst[sample] = SwapFloat(src[sample]); - } + if (subcycle == fNumPackets - 1) { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fCompressedBuffer[port_index] + subcycle * fSubPeriodBytesSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize); + } else { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fCompressedBuffer[port_index] + subcycle * fSubPeriodBytesSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); + } + + if (subcycle != fLastSubCycle + 1) + jack_error("Packet(s) missing from... %d %d", fLastSubCycle, subcycle); + + fLastSubCycle = subcycle; + return copy_size; + } + + int NetCeltAudioBuffer::RenderToNetwork(int subcycle, size_t total_size) + { + if (subcycle == fNumPackets - 1) { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fCompressedBuffer[port_index] + subcycle * fSubPeriodBytesSize, fLastSubPeriodBytesSize); + return fNPorts * fLastSubPeriodBytesSize; + } else { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fCompressedBuffer[port_index] + subcycle * fSubPeriodBytesSize, fSubPeriodBytesSize); + return fNPorts * fSubPeriodBytesSize; } + + return fNPorts * fSubPeriodBytesSize; } -#else +#endif - void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) + NetIntAudioBuffer::NetIntAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) + : fNetBuffer(net_buffer) { - for ( int port_index = 0; port_index < fNPorts; port_index++ ) - memcpy ( fNetBuffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize ); + int res1, res2; + + fNPorts = nports; + fPeriodSize = params->fPeriodSize; + + fPortBuffer = new sample_t* [fNPorts]; + for (int port_index = 0; port_index < fNPorts; port_index++) + fPortBuffer[port_index] = NULL; + + fIntBuffer = new short* [fNPorts]; + for (int port_index = 0; port_index < fNPorts; port_index++) + fIntBuffer[port_index] = new short[fPeriodSize]; + + fCompressedSizeByte = (params->fPeriodSize * sizeof(short)); + + jack_log("fCompressedSizeByte %d", fCompressedSizeByte); + + res1 = (fNPorts * fCompressedSizeByte) % (params->fMtu - sizeof(packet_header_t)); + res2 = (fNPorts * fCompressedSizeByte) / (params->fMtu - sizeof(packet_header_t)); + + jack_log("res1 = %d res2 = %d", res1, res2); + + fNumPackets = (res1) ? (res2 + 1) : res2; + + fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets; + fSubPeriodSize = fSubPeriodBytesSize / sizeof(short); + + fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets; + fLastSubPeriodSize = fLastSubPeriodBytesSize / sizeof(short); + + jack_log("fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); + + fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate); + fCycleSize = params->fMtu * fNumPackets; + + fLastSubCycle = -1; + return; + } + + NetIntAudioBuffer::~NetIntAudioBuffer() + { + for (int port_index = 0; port_index < fNPorts; port_index++) + delete [] fIntBuffer[port_index]; + + delete [] fIntBuffer; + delete [] fPortBuffer; } - void NetAudioBuffer::RenderToJackPorts ( int subcycle ) + size_t NetIntAudioBuffer::GetCycleSize() { - for ( int port_index = 0; port_index < fNPorts; port_index++ ) - memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize ); + return fCycleSize; } -#endif + float NetIntAudioBuffer::GetCycleDuration() + { + return fCycleDuration; + } + + int NetIntAudioBuffer::GetNumPackets() + { + return fNumPackets; + } + + void NetIntAudioBuffer::SetBuffer(int index, sample_t* buffer) + { + fPortBuffer[index] = buffer; + } + + sample_t* NetIntAudioBuffer::GetBuffer(int index) + { + return fPortBuffer[index]; + } + + int NetIntAudioBuffer::RenderFromJackPorts() + { + for (int port_index = 0; port_index < fNPorts; port_index++) { + for (unsigned int frame = 0; frame < fPeriodSize; frame++) + fIntBuffer[port_index][frame] = short(fPortBuffer[port_index][frame] * 32768.f); + } + + return fNPorts * fCompressedSizeByte; // in bytes + } + + int NetIntAudioBuffer::RenderToJackPorts() + { + for (int port_index = 0; port_index < fNPorts; port_index++) { + float coef = 1.f / 32768.f; + for (unsigned int frame = 0; frame < fPeriodSize; frame++) + fPortBuffer[port_index][frame] = float(fIntBuffer[port_index][frame] * coef); + } + + fLastSubCycle = -1; + //return fPeriodSize * sizeof(sample_t); // in bytes; TODO + return 0; + } + + //network<->buffer + int NetIntAudioBuffer::RenderFromNetwork(int cycle, int subcycle, size_t copy_size) + { + if (subcycle == fNumPackets - 1) { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fIntBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize); + } else { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fIntBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); + } + + if (subcycle != fLastSubCycle + 1) + jack_error("Packet(s) missing from... %d %d", fLastSubCycle, subcycle); + + fLastSubCycle = subcycle; + return copy_size; + } + + int NetIntAudioBuffer::RenderToNetwork(int subcycle, size_t total_size) + { + if (subcycle == fNumPackets - 1) { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fIntBuffer[port_index] + subcycle * fSubPeriodSize, fLastSubPeriodBytesSize); + return fNPorts * fLastSubPeriodBytesSize; + } else { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fIntBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize); + return fNPorts * fSubPeriodBytesSize; + } + } + +// Buffered + +/* + NetBufferedAudioBuffer::NetBufferedAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) + { + fMaxCycle = 0; + fNetBuffer = net_buffer; + + for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) { + fPortBuffer[i].Init(params, nports); + } + + fJackPortBuffer = new sample_t* [nports]; + for ( uint32_t port_index = 0; port_index < nports; port_index++ ) + fJackPortBuffer[port_index] = NULL; + } + + NetBufferedAudioBuffer::~NetBufferedAudioBuffer() + { + delete [] fJackPortBuffer; + } + + size_t NetBufferedAudioBuffer::GetCycleSize() + { + return fPortBuffer[0].GetCycleSize(); + } + + void NetBufferedAudioBuffer::SetBuffer ( int index, sample_t* buffer ) + { + fJackPortBuffer[index] = buffer; + } + + sample_t* NetBufferedAudioBuffer::GetBuffer ( int index ) + { + return fJackPortBuffer[index]; + } + + void NetBufferedAudioBuffer::RenderFromJackPorts (int subcycle ) + { + fPortBuffer[0].RenderFromJackPorts(fNetBuffer, subcycle); // Always use first buffer... + } + + void NetBufferedAudioBuffer::RenderToJackPorts (int cycle, int subcycle) + { + if (cycle < fMaxCycle) { + jack_info("Wrong order fCycle %d subcycle %d fMaxCycle %d", cycle, subcycle, fMaxCycle); + } + fPortBuffer[cycle % AUDIO_BUFFER_SIZE].RenderToJackPorts(fNetBuffer, subcycle); + } + + void NetBufferedAudioBuffer::FinishRenderToJackPorts (int cycle) + { + fMaxCycle = std::max(fMaxCycle, cycle); + fPortBuffer[(cycle + 1) % AUDIO_BUFFER_SIZE].Copy(fJackPortBuffer); // Copy internal buffer in JACK ports + } + */ // SessionParams ************************************************************************************ @@ -232,8 +650,7 @@ namespace Jack dst_params->fReturnMidiChannels = htonl ( src_params->fReturnMidiChannels ); dst_params->fSampleRate = htonl ( src_params->fSampleRate ); dst_params->fPeriodSize = htonl ( src_params->fPeriodSize ); - dst_params->fFramesPerPacket = htonl ( src_params->fFramesPerPacket ); - dst_params->fBitdepth = htonl ( src_params->fBitdepth ); + dst_params->fSampleEncoder = htonl ( src_params->fSampleEncoder ); dst_params->fSlaveSyncMode = htonl ( src_params->fSlaveSyncMode ); } @@ -250,15 +667,26 @@ namespace Jack dst_params->fReturnMidiChannels = ntohl ( src_params->fReturnMidiChannels ); dst_params->fSampleRate = ntohl ( src_params->fSampleRate ); dst_params->fPeriodSize = ntohl ( src_params->fPeriodSize ); - dst_params->fFramesPerPacket = ntohl ( src_params->fFramesPerPacket ); - dst_params->fBitdepth = ntohl ( src_params->fBitdepth ); + dst_params->fSampleEncoder = ntohl ( src_params->fSampleEncoder ); dst_params->fSlaveSyncMode = ntohl ( src_params->fSlaveSyncMode ); } SERVER_EXPORT void SessionParamsDisplay ( session_params_t* params ) { - char bitdepth[16]; - ( params->fBitdepth ) ? sprintf ( bitdepth, "%u", params->fBitdepth ) : sprintf ( bitdepth, "%s", "float" ); + char encoder[16]; + switch ( params->fSampleEncoder ) + { + case JackFloatEncoder: + strcpy ( encoder, "float" ); + break; + case JackIntEncoder: + strcpy ( encoder, "integer" ); + break; + case JackCeltEncoder: + strcpy ( encoder, "CELT" ); + break; + } + char mode[8]; switch ( params->fNetworkMode ) { @@ -284,9 +712,17 @@ namespace Jack jack_info ( "Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels ); jack_info ( "Sample rate : %u frames per second", params->fSampleRate ); jack_info ( "Period size : %u frames per period", params->fPeriodSize ); - jack_info ( "Frames per packet : %u", params->fFramesPerPacket ); - jack_info ( "Packet per period : %u", (params->fFramesPerPacket != 0) ? params->fPeriodSize / params->fFramesPerPacket : 0); - jack_info ( "Bitdepth : %s", bitdepth ); + switch (params->fSampleEncoder) { + case (JackFloatEncoder): + jack_info ( "SampleEncoder : %s", "Float" ); + break; + case (JackIntEncoder): + jack_info ( "SampleEncoder : %s", "16 bits integer"); + break; + case (JackCeltEncoder): + jack_info ( "SampleEncoder : %s", "CELT"); + break; + }; jack_info ( "Slave mode : %s", ( params->fSlaveSyncMode ) ? "sync" : "async" ); jack_info ( "Network mode : %s", mode ); jack_info ( "****************************************************" ); @@ -340,9 +776,7 @@ namespace Jack { memcpy(dst_header, src_header, sizeof(packet_header_t)); dst_header->fID = htonl ( src_header->fID ); - dst_header->fMidiDataSize = htonl ( src_header->fMidiDataSize ); - dst_header->fBitdepth = htonl ( src_header->fBitdepth ); - dst_header->fNMidiPckt = htonl ( src_header->fNMidiPckt ); + dst_header->fNumPacket = htonl ( src_header->fNumPacket ); dst_header->fPacketSize = htonl ( src_header->fPacketSize ); dst_header->fCycle = htonl ( src_header->fCycle ); dst_header->fSubCycle = htonl ( src_header->fSubCycle ); @@ -353,9 +787,7 @@ namespace Jack { memcpy(dst_header, src_header, sizeof(packet_header_t)); dst_header->fID = ntohl ( src_header->fID ); - dst_header->fMidiDataSize = ntohl ( src_header->fMidiDataSize ); - dst_header->fBitdepth = ntohl ( src_header->fBitdepth ); - dst_header->fNMidiPckt = ntohl ( src_header->fNMidiPckt ); + dst_header->fNumPacket = ntohl ( src_header->fNumPacket ); dst_header->fPacketSize = ntohl ( src_header->fPacketSize ); dst_header->fCycle = ntohl ( src_header->fCycle ); dst_header->fSubCycle = ntohl ( src_header->fSubCycle ); @@ -365,15 +797,13 @@ namespace Jack SERVER_EXPORT void PacketHeaderDisplay ( packet_header_t* header ) { char bitdepth[16]; - ( header->fBitdepth ) ? sprintf ( bitdepth, "%u", header->fBitdepth ) : sprintf ( bitdepth, "%s", "float" ); jack_info ( "********************Header********************" ); jack_info ( "Data type : %c", header->fDataType ); jack_info ( "Data stream : %c", header->fDataStream ); jack_info ( "ID : %u", header->fID ); jack_info ( "Cycle : %u", header->fCycle ); jack_info ( "SubCycle : %u", header->fSubCycle ); - jack_info ( "Midi packets : %u", header->fNMidiPckt ); - jack_info ( "Midi data size : %u", header->fMidiDataSize ); + jack_info ( "Midi packets : %u", header->fNumPacket ); jack_info ( "Last packet : '%s'", ( header->fIsLastPckt ) ? "yes" : "no" ); jack_info ( "Bitdepth : %s", bitdepth ); jack_info ( "**********************************************" ); diff --git a/common/JackNetTool.h b/common/JackNetTool.h index 725d100c..8466253d 100644 --- a/common/JackNetTool.h +++ b/common/JackNetTool.h @@ -47,6 +47,13 @@ namespace Jack typedef struct sockaddr socket_address_t; typedef struct in_addr address_t; typedef jack_default_audio_sample_t sample_t; + + enum JackNetEncoder { + + JackFloatEncoder = 0, + JackIntEncoder = 1, + JackCeltEncoder = 2, + }; //session params ****************************************************************************** @@ -67,8 +74,8 @@ namespace Jack are kept in LITTLE_ENDIAN format (to avoid 2 conversions in the more common LITTLE_ENDIAN <==> LITTLE_ENDIAN connection case). */ - #define MASTER_PROTOCOL 1 - #define SLAVE_PROTOCOL 1 + #define MASTER_PROTOCOL 2 + #define SLAVE_PROTOCOL 2 struct _session_params { @@ -87,8 +94,8 @@ namespace Jack int32_t fReturnMidiChannels; //number of slave->master midi channels uint32_t fSampleRate; //session sample rate uint32_t fPeriodSize; //period size - uint32_t fFramesPerPacket; //complete frames per packet - uint32_t fBitdepth; //samples bitdepth (unused) + uint32_t fSampleEncoder; //samples encoder + uint32_t fKBps; // KB per second for CELT encoder uint32_t fSlaveSyncMode; //is the slave in sync mode ? char fNetworkMode; //fast, normal or slow mode }; @@ -158,15 +165,11 @@ namespace Jack char fDataType; //a for audio, m for midi and s for sync char fDataStream; //s for send, r for return uint32_t fID; //unique ID of the slave - uint32_t fBitdepth; //bitdepth of the data samples - uint32_t fMidiDataSize; //size of midi data in bytes - uint32_t fNMidiPckt; //number of midi packets of the cycle + uint32_t fNumPacket; //number of data packets of the cycle uint32_t fPacketSize; //packet size in bytes uint32_t fCycle; //process cycle counter uint32_t fSubCycle; //midi/audio subcycle counter uint32_t fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n') - char fASyncWrongCycle; //is the current async cycle wrong (slave's side; 'y' or 'n') - char fFree[26]; //unused }; //net timebase master @@ -199,8 +202,8 @@ namespace Jack int32_t fState; //current cycle state jack_position_t fPosition; //current cycle position }; - -//midi data *********************************************************************************** + + //midi data *********************************************************************************** /** \Brief Midi buffer and operations class @@ -220,24 +223,35 @@ namespace Jack class SERVER_EXPORT NetMidiBuffer { private: + int fNPorts; size_t fMaxBufsize; int fMaxPcktSize; char* fBuffer; char* fNetBuffer; JackMidiBuffer** fPortBuffer; + + size_t fCycleSize; // needed size in bytes ofr an entire cycle public: + NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); ~NetMidiBuffer(); void Reset(); - size_t GetSize(); + + // needed size in bytes for an entire cycle + size_t GetCycleSize(); + + int GetNumPackets(); + //utility void DisplayEvents(); + //jack<->buffer int RenderFromJackPorts(); int RenderToJackPorts(); + //network<->buffer int RenderFromNetwork ( int subcycle, size_t copy_size ); int RenderToNetwork ( int subcycle, size_t total_size ); @@ -248,6 +262,36 @@ namespace Jack // audio data ********************************************************************************* + class SERVER_EXPORT NetAudioBuffer + { + + public: + + NetAudioBuffer () + {} + virtual ~NetAudioBuffer() + {} + + // needed syze in bytes ofr an entire cycle + virtual size_t GetCycleSize() = 0; + + // cycle duration in sec + virtual float GetCycleDuration() = 0; + + virtual int GetNumPackets() = 0; + + //jack<->buffer + virtual int RenderFromJackPorts () = 0; + virtual int RenderToJackPorts () = 0; + + //network<->buffer + virtual int RenderFromNetwork ( int cycle, int subcycle, size_t copy_size ) = 0; + virtual int RenderToNetwork (int subcycle, size_t total_size ) = 0; + + virtual void SetBuffer ( int index, sample_t* buffer ) = 0; + virtual sample_t* GetBuffer ( int index ) = 0; + }; + /** \Brief Audio buffer and operations class @@ -257,28 +301,417 @@ namespace Jack So there is no need of an intermediate buffer as in NetMidiBuffer. */ + + struct JackPortList { + + jack_nframes_t fPeriodSize; + jack_nframes_t fSubPeriodSize; + size_t fSubPeriodBytesSize; + sample_t** fPortBuffer; + int fNPorts; + size_t fCycleSize; // needed size in bytes for an entire cycle + float fCycleDuration; // in sec + + int fLastSubCycle; + + JackPortList(session_params_t* params, uint32_t nports) + { + fNPorts = nports; + fPeriodSize = params->fPeriodSize; + + if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) { + fSubPeriodSize = params->fPeriodSize; + } else { + jack_nframes_t period = (int) powf(2.f, (int) (log (float ((params->fMtu - sizeof(packet_header_t))) + / (max(params->fReturnAudioChannels, params->fSendAudioChannels) * sizeof(sample_t))) / log(2.))); + fSubPeriodSize = (period > params->fPeriodSize) ? params->fPeriodSize : period; + } + + fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t); + + fPortBuffer = new sample_t* [fNPorts]; + for (int port_index = 0; port_index < fNPorts; port_index++) + fPortBuffer[port_index] = NULL; + + fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate); + fCycleSize = params->fMtu * (fPeriodSize / fSubPeriodSize); + + fLastSubCycle = -1; + } + + int GetNumPackets() + { + return fPeriodSize / fSubPeriodSize; + } + + JackPortList() + { + fNPorts = 0; + fPeriodSize = 0; + fSubPeriodSize = 0; + fSubPeriodBytesSize = 0; + fPortBuffer = 0; + } + + ~JackPortList() + { + delete [] fPortBuffer; + } + + void SetBuffer( int index, sample_t* buffer ) + { + fPortBuffer[index] = buffer; + } + + sample_t* GetBuffer ( int index ) + { + return fPortBuffer[index]; + } + + void Copy(sample_t** buffers) + { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(buffers[port_index], fPortBuffer[port_index], fPeriodSize * sizeof(float)); + } + + // needed syze in bytes ofr an entire cycle + size_t GetCycleSize() + { + return fCycleSize; + } + + // cycle duration in sec + float GetCycleDuration() + { + return fCycleDuration; + } + + #ifdef __BIG_ENDIAN__ + + static inline float SwapFloat(float f) + { + union + { + float f; + unsigned char b[4]; + } dat1, dat2; + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; + } + + int RenderFromJackPorts () + { + return fNPorts * fSubPeriodBytesSize; // in bytes + } + + int RenderToJackPorts () + { + return fPeriodSize * sizeof(sample_t); // in bytes TODO + } + + //network<->buffer + int RenderFromNetwork(char* net_buffer, int cycle, int subcycle, size_t copy_size) + { + for ( int port_index = 0; port_index < fNPorts; port_index++ ) { + float* src = (float*)(net_buffer + port_index * fSubPeriodBytesSize); + float* dst = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); + for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { + dst[sample] = SwapFloat(src[sample]); + } + } + + return copy_size; + } + + int RenderToNetwork(char* net_buffer, int subcycle, size_t total_size) + { + + for ( int port_index = 0; port_index < fNPorts; port_index++ ) { + float* src = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); + float* dst = (float*)(net_buffer + port_index * fSubPeriodBytesSize); + for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { + dst[sample] = SwapFloat(src[sample]); + } + } + + return fNPorts * fSubPeriodBytesSize; + } + + #else + + int RenderFromJackPorts () + { + return fNPorts * fSubPeriodBytesSize; // in bytes + } + + int RenderToJackPorts () + { + fLastSubCycle = -1; + return fPeriodSize * sizeof(sample_t); // in bytes; TODO + } + + //network<->buffer + int RenderFromNetwork(char* net_buffer, int cycle, int subcycle, size_t copy_size) + { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(fPortBuffer[port_index] + subcycle * fSubPeriodSize, net_buffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); + if (subcycle != fLastSubCycle + 1) { + jack_error("Packet(s) missing from... %d %d", fLastSubCycle, subcycle); + } + fLastSubCycle = subcycle; + return copy_size; + } + + int RenderToNetwork(char* net_buffer,int subcycle, size_t total_size) + { + for (int port_index = 0; port_index < fNPorts; port_index++) + memcpy(net_buffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize); + + return fNPorts * fSubPeriodBytesSize; + } + + #endif + + }; + + struct JackPortListAllocate : public JackPortList { + + JackPortListAllocate() + { + fNPorts = 0; + fPeriodSize = 0; + fSubPeriodSize = 0; + fSubPeriodBytesSize = 0; + fPortBuffer = 0; + } + + ~JackPortListAllocate() + { + for (int port_index = 0; port_index < fNPorts; port_index++) + delete [] fPortBuffer[port_index]; + delete [] fPortBuffer; + } + + void Init(session_params_t* params, uint32_t nports) + { + fNPorts = nports; + fPeriodSize = params->fPeriodSize; + + if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) { + fSubPeriodSize = params->fPeriodSize; + } else { + jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ((params->fMtu - sizeof(packet_header_t))) + / ( max ( params->fReturnAudioChannels, params->fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) ); + fSubPeriodSize = ( period > params->fPeriodSize ) ? params->fPeriodSize : period; + } + + fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); + fPortBuffer = new sample_t* [fNPorts]; + for ( int port_index = 0; port_index < fNPorts; port_index++ ) + fPortBuffer[port_index] = new sample_t[fPeriodSize]; + } + + }; - class SERVER_EXPORT NetAudioBuffer + class SERVER_EXPORT NetFloatAudioBuffer : public NetAudioBuffer { private: - int fNPorts; + + JackPortList fPortBuffer; + char* fNetBuffer; + + public: + + NetFloatAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); + ~NetFloatAudioBuffer(); + + // needed size in bytes for an entire cycle + size_t GetCycleSize(); + + // cycle duration in sec + float GetCycleDuration() + { + return fPortBuffer.GetCycleDuration(); + } + + int GetNumPackets() + { + return fPortBuffer.GetNumPackets(); + } + + //jack<->buffer + int RenderFromJackPorts (); + int RenderToJackPorts (); + + void SetBuffer ( int index, sample_t* buffer ); + sample_t* GetBuffer ( int index ); + + //network<->buffer + int RenderFromNetwork ( int cycle, int subcycle, size_t copy_size ); + int RenderToNetwork (int subcycle, size_t total_size ); + }; + +#define CELT 1 + +#ifdef CELT + +#include + + class SERVER_EXPORT NetCeltAudioBuffer : public NetAudioBuffer + { + private: + + CELTMode ** fCeltMode; + CELTEncoder ** fCeltEncoder; + CELTDecoder ** fCeltDecoder; + + int fCompressedSizeByte; jack_nframes_t fPeriodSize; - jack_nframes_t fSubPeriodSize; + int fNumPackets; + float fCycleDuration; // in sec + size_t fCycleSize; // needed size in bytes for an entire cycle + size_t fSubPeriodBytesSize; + size_t fLastSubPeriodBytesSize; + + sample_t** fPortBuffer; char* fNetBuffer; + unsigned char ** fCompressedBuffer; + + int fNPorts; + + int fLastSubCycle; + + void FreeCelt(); + + public: + + NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps); + ~NetCeltAudioBuffer(); + + // needed size in bytes for an entire cycle + size_t GetCycleSize(); + + // cycle duration in sec + float GetCycleDuration(); + + int GetNumPackets(); + + void SetBuffer(int index, sample_t* buffer); + sample_t* GetBuffer(int index); + + //jack<->buffer + int RenderFromJackPorts(); + int RenderToJackPorts(); + + //network<->buffer + int RenderFromNetwork(int cycle, int subcycle, size_t copy_size); + int RenderToNetwork(int subcycle, size_t total_size); + }; + +#endif + + class SERVER_EXPORT NetIntAudioBuffer : public NetAudioBuffer + { + private: + + int fCompressedSizeByte; + jack_nframes_t fPeriodSize; + + int fNumPackets; + float fCycleDuration; // in sec + size_t fCycleSize; // needed size in bytes for an entire cycle + + size_t fSubPeriodSize; + size_t fSubPeriodBytesSize; + size_t fLastSubPeriodSize;; + size_t fLastSubPeriodBytesSize; + sample_t** fPortBuffer; + char* fNetBuffer; + short ** fIntBuffer; + + int fNPorts; + + int fLastSubCycle; + public: - NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); - ~NetAudioBuffer(); + + NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer); + ~NetIntAudioBuffer(); + + // needed size in bytes for an entire cycle + size_t GetCycleSize(); + + // cycle duration in sec + float GetCycleDuration(); + + int GetNumPackets(); + + void SetBuffer(int index, sample_t* buffer); + sample_t* GetBuffer(int index); + + //jack<->buffer + int RenderFromJackPorts(); + int RenderToJackPorts(); + + //network<->buffer + int RenderFromNetwork(int cycle, int subcycle, size_t copy_size); + int RenderToNetwork(int subcycle, size_t total_size); + }; - size_t GetSize(); + + #define AUDIO_BUFFER_SIZE 8 + + /* + class SERVER_EXPORT NetBufferedAudioBuffer : public NetAudioBuffer + { + + private: + char* fNetBuffer; + JackPortListAllocate fPortBuffer[AUDIO_BUFFER_SIZE]; + sample_t** fJackPortBuffer; + int fMaxCycle; + + public: + NetBufferedAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); + ~NetBufferedAudioBuffer(); + + // needed syze in bytes ofr an entire cycle + size_t GetCycleSize(); + + // cycle duration in sec + float GetCycleDuration() + { + return fPortBuffer[0].GetCycleDuration(); + } + //jack<->buffer - void RenderFromJackPorts ( int subcycle ); - void RenderToJackPorts ( int subcycle ); + int RenderFromJackPorts (int subcycle ); + int RenderToJackPorts ( int cycle, int subcycle); + //void FinishRenderToJackPorts (int cycle); + + //network<->buffer + int RenderFromNetwork ( int subcycle, size_t copy_size ) + { + // TODO + return 0; + } + int RenderToNetwork ( int subcycle, size_t total_size ) + { + // TODO + return 0; + } void SetBuffer ( int index, sample_t* buffer ); sample_t* GetBuffer ( int index ); }; + */ //utility ************************************************************************************* diff --git a/common/JackResampler.cpp b/common/JackResampler.cpp index 57220295..f2d49189 100644 --- a/common/JackResampler.cpp +++ b/common/JackResampler.cpp @@ -39,6 +39,7 @@ JackResampler::~JackResampler() void JackResampler::Reset(unsigned int new_size) { fRingBufferSize = new_size; + jack_ringbuffer_reset(fRingBuffer); jack_ringbuffer_reset_size(fRingBuffer, sizeof(jack_default_audio_sample_t) * fRingBufferSize); jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize / 2)); } @@ -81,6 +82,34 @@ unsigned int JackResampler::Write(jack_default_audio_sample_t* buffer, unsigned } } +unsigned int JackResampler::Read(void* buffer, unsigned int bytes) +{ + size_t len = jack_ringbuffer_read_space(fRingBuffer); + jack_log("JackResampler::Read input available = %ld", len); + + if (len < bytes) { + jack_error("JackResampler::Read : producer too slow, missing bytes = %d", bytes); + return 0; + } else { + jack_ringbuffer_read(fRingBuffer, (char*)buffer, bytes); + return bytes; + } +} + +unsigned int JackResampler::Write(void* buffer, unsigned int bytes) +{ + size_t len = jack_ringbuffer_write_space(fRingBuffer); + jack_log("JackResampler::Write output available = %ld", len); + + if (len < bytes) { + jack_error("JackResampler::Write : consumer too slow, skip bytes = %d", bytes); + return 0; + } else { + jack_ringbuffer_write(fRingBuffer, (char*)buffer, bytes); + return bytes; + } +} + unsigned int JackResampler::ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames) { return Read(buffer, frames); diff --git a/common/JackResampler.h b/common/JackResampler.h index d5994c8e..89334c77 100644 --- a/common/JackResampler.h +++ b/common/JackResampler.h @@ -61,6 +61,9 @@ class JackResampler virtual unsigned int Read(jack_default_audio_sample_t* buffer, unsigned int frames); virtual unsigned int Write(jack_default_audio_sample_t* buffer, unsigned int frames); + virtual unsigned int Read(void* buffer, unsigned int bytes); + virtual unsigned int Write(void* buffer, unsigned int bytes); + virtual unsigned int ReadSpace(); virtual unsigned int WriteSpace(); diff --git a/common/JackTools.h b/common/JackTools.h index f7d5ce1e..50451e04 100644 --- a/common/JackTools.h +++ b/common/JackTools.h @@ -141,7 +141,7 @@ namespace Jack T Add ( T measure_point ) { - return fCurrentMeasure[fMeasureId++] = measure_point; + return fCurrentMeasure[fMeasureId++] = measure_point; } uint32_t AddLast ( T measure_point ) diff --git a/common/JackWaitThreadedDriver.h b/common/JackWaitThreadedDriver.h index d885f2d4..83a8e351 100644 --- a/common/JackWaitThreadedDriver.h +++ b/common/JackWaitThreadedDriver.h @@ -70,6 +70,7 @@ class SERVER_EXPORT JackWaitThreadedDriver : public JackThreadedDriver } else { jack_error("Initing net driver fails..."); } + return false; } diff --git a/common/jack/net.h b/common/jack/net.h new file mode 100644 index 00000000..54de2412 --- /dev/null +++ b/common/jack/net.h @@ -0,0 +1,321 @@ +/* + Copyright (C) 2009-2010 Grame + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __net_h__ +#define __net_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#define DEFAULT_MULTICAST_IP "225.3.19.154" +#define DEFAULT_PORT 19000 +#define DEFAULT_MTU 1500 +#define MASTER_NAME_SIZE 256 + +#define SOCKET_ERROR -1 + +enum JackNetMode { + + JackFastMode = 'f', + JackNormalMode = 'n', + JackSlowMode = 's', +}; + +enum JackNetEncoder { + + JackFloatEncoder = 0, // Samples are transmitted as float + JackIntEncoder = 1, // Samples are transmitted as 16 bits integer + JackCeltEncoder = 2, // Samples are transmitted using CELT codec (http://www.celt-codec.org/) +}; + +typedef struct { + + int audio_input; // from master or to slave + int audio_output; // to master or from slave + int midi_input; // from master or to slave + int midi_output; // to master or from slave + int mtu; // network Maximum Transmission Unit + int time_out; // in second, -1 means in infinite + int encoder; // Encoder type (one of JackNetEncoder) + int kbps; // KB per second for CELT encoder + char mode; + +} jack_slave_t; + +typedef struct { + + jack_nframes_t buffer_size; + jack_nframes_t sample_rate; + char master_name[MASTER_NAME_SIZE]; + +} jack_master_t; + +/** + * jack_net_t is an opaque type. You may only access it using the + * API provided. + */ +typedef struct _jack_net_slave jack_net_slave_t; + + /** + * Open a network connection with the master machine. + * @param ip the multicast address of the master + * @param port the connection port + * @param request a connection request structure + * @param result a connection result structure + * + * @return Opaque net handle if successful or NULL in case of error. + */ +jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result); + +/** + * Close the network connection with the master machine. + * @param net the network connection to be closed + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_net_slave_close(jack_net_slave_t* net); + +/** + * Prototype for Process callback. + * @param nframes buffer size + * @param audio_input number of audio inputs + * @param audio_input_buffer an array of audio input buffers (from master) + * @param midi_input number of MIDI inputs + * @param midi_input_buffer an array of MIDI input buffers (from master) + * @param audio_output number of audio outputs + * @param audio_output_buffer an array of audio output buffers (to master) + * @param midi_output number of MIDI outputs + * @param midi_output_buffer an array of MIDI output buffers (to master) + * @param arg pointer to a client supplied structure supplied by jack_set_net_process_callback(). + * + * @return zero on success, non-zero on error + */ +typedef int (* JackNetSlaveProcessCallback) (jack_nframes_t buffer_size, + int audio_input, + float** audio_input_buffer, + int midi_input, + void** midi_input_buffer, + int audio_output, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, + void* data); + +/** + * Set network process callback. + * @param net the network connection + * @param net_callback the process callback + * @param arg pointer to a client supplied structure + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_net_slave_process_callback(jack_net_slave_t * net, JackNetSlaveProcessCallback net_callback, void *arg); + +/** + * Start processing thread, the net_callback will start to be called. + * @param net the network connection + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_net_slave_activate(jack_net_slave_t* net); + +/** + * Stop processing thread. + * @param net the network connection + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_net_slave_deactivate(jack_net_slave_t* net); + +/** + * Prototype for BufferSize callback. + * @param nframes buffer size + * @param arg pointer to a client supplied structure supplied by jack_set_net_buffer_size_callback(). + * + * @return zero on success, non-zero on error + */ +typedef int (*JackNetSlaveBufferSizeCallback)(jack_nframes_t nframes, void *arg); + +/** + * Prototype for SampleRate callback + * @param nframes sample rate + * @param arg pointer to a client supplied structure supplied by jack_set_net_sample_rate_callback(). + * + * @return zero on success, non-zero on error + */ +typedef int (*JackNetSlaveSampleRateCallback)(jack_nframes_t nframes, void *arg); + +/** + * Set network buffer size callback. + * @param net the network connection + * @param bufsize_callback the buffer size callback + * @param arg pointer to a client supplied structure + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg); + +/** + * Set network sample rate callback. + * @param net the network connection + * @param samplerate_callback the sample rate callback + * @param arg pointer to a client supplied structure + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg); + +/** + * Prototype for server Shutdown callback (if not set, the client will just restart, waiting for an available master again.) + * @param arg pointer to a client supplied structure supplied by jack_set_net_shutdown_callback(). + */ +typedef void (*JackNetSlaveShutdownCallback)(void* data); + +/** + * Set network shutdown callback. + * @param net the network connection + * @param shutdown_callback the shutdown callback + * @param arg pointer to a client supplied structure + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg); + +/** + * jack_net_t is an opaque type. You may only access it using the + * API provided. + */ +typedef struct _jack_net_master jack_net_master_t; + + /** + * Open a network connection with the slave machine. + * @param ip the multicast address of the master + * @param port the connection port + * @param request a connection request structure + * @param result a connection result structure + * + * @return Opaque net handle if successful or NULL in case of error. + */ +jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result); + +/** + * Close the network connection with the master machine. + * @param net the network connection to be closed + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_net_master_close(jack_net_master_t* net); + +/** + * Receive sync and data from the network + * @param net the network connection + * @param audio_input number of audio inputs + * @param audio_input_buffer an array of audio input buffers + * @param midi_input number of MIDI inputs + * @param midi_input_buffer an array of MIDI input buffers + * + * @return zero on success, non-zero on error + */ +int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); + +/** + * Send sync and data to the network + * @param net the network connection + * @param audio_output number of audio outputs + * @param audio_output_buffer an array of audio output buffers + * @param midi_output number of MIDI ouputs + * @param midi_output_buffer an array of MIDI output buffers + * + * @return zero on success, non-zero on error + */ +int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); + +// Experimental Adapter API + +/** + * jack_adapter_t is an opaque type. You may only access it using the + * API provided. + */ +typedef struct _jack_adapter jack_adapter_t; + +/** + * Create an adapter. + * @param input number of audio inputs + * @param output of audio outputs + * @param host_buffer_size the host buffer size in frames + * @param host_sample_rate the host buffer sample rate + * @param adapted_buffer_size the adapted buffer size in frames + * @param adapted_sample_rate the adapted buffer sample rate + * + * @return 0 on success, otherwise a non-zero error code + */ +jack_adapter_t* jack_create_adapter(int input, int output, + jack_nframes_t host_buffer_size, + jack_nframes_t host_sample_rate, + jack_nframes_t adapted_buffer_size, + jack_nframes_t adapted_sample_rate); + +/** + * Destroy an adapter. + * @param adapter the adapter to be destroyed + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_destroy_adapter(jack_adapter_t* adapter); + +/** + * Flush internal state of an adapter. + * @param adapter the adapter to be flushed + * + * @return 0 on success, otherwise a non-zero error code + */ +void jack_flush_adapter(jack_adapter_t* adapter); + +/** + * Push input to and pull output from adapter ringbuffer + * @param adapter the adapter + * @param input an array of audio input buffers + * @param output an array of audio ouput buffers + * @param frames number of frames + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); + +/** + * Pull input to and push output from adapter ringbuffer + * @param adapter the adapter + * @param input an array of audio input buffers + * @param output an array of audio ouput buffers + * @param frames number of frames + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); + +#ifdef __cplusplus +} +#endif + +#endif /* __net_h__ */ diff --git a/common/ringbuffer.c b/common/ringbuffer.c index 45ee27b3..9dc05184 100644 --- a/common/ringbuffer.c +++ b/common/ringbuffer.c @@ -59,7 +59,7 @@ EXPORT void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz); EXPORT size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, size_t cnt); void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt); -size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); +size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); /* Create a new ringbuffer to hold at least `sz' bytes of data. The actual buffer size is rounded up to the next power of two. */ @@ -69,13 +69,13 @@ jack_ringbuffer_create (size_t sz) { int power_of_two; jack_ringbuffer_t *rb; - + if ((rb = (jack_ringbuffer_t *) malloc (sizeof (jack_ringbuffer_t))) == NULL) { return NULL; } - + for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++); - + rb->size = 1 << power_of_two; rb->size_mask = rb->size; rb->size_mask -= 1; @@ -86,7 +86,7 @@ jack_ringbuffer_create (size_t sz) return NULL; } rb->mlocked = 0; - + return rb; } @@ -126,6 +126,7 @@ jack_ringbuffer_reset (jack_ringbuffer_t * rb) { rb->read_ptr = 0; rb->write_ptr = 0; + memset(rb->buf, 0, rb->size); } /* Reset the read and write pointers to zero. This is not thread @@ -149,10 +150,10 @@ EXPORT size_t jack_ringbuffer_read_space (const jack_ringbuffer_t * rb) { size_t w, r; - + w = rb->write_ptr; r = rb->read_ptr; - + if (w > r) { return w - r; } else { @@ -219,8 +220,8 @@ jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt) return to_read; } -/* The copying data reader w/o read pointer advance. Copy at most - `cnt' bytes from `rb' to `dest'. Returns the actual number of bytes +/* The copying data reader w/o read pointer advance. Copy at most + `cnt' bytes from `rb' to `dest'. Returns the actual number of bytes copied. */ EXPORT size_t diff --git a/common/wscript b/common/wscript index 8b10f1b7..84e4a6b7 100644 --- a/common/wscript +++ b/common/wscript @@ -186,6 +186,38 @@ def build(bld): if bld.env['IS_SUN']: serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") + netlib = bld.new_task_gen('cxx', 'shlib') + netlib.features.append('cc') + netlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] + netlib.includes = includes + netlib.name = 'netlib' + netlib.target = 'jacknet' + netlib.uselib = 'SAMPLERATE' + netlib.install_path = '${LIBDIR}' + netlib.source = ['JackNetAPI.cpp', + 'JackNetInterface.cpp', + 'JackNetTool.cpp', + 'JackAudioAdapterInterface.cpp', + 'JackLibSampleRateResampler.cpp', + 'JackResampler.cpp', + 'JackGlobals.cpp', + 'ringbuffer.c'] + + if bld.env['IS_LINUX']: + netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../linux/JackLinuxTime.c'] + netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") + + if bld.env['IS_SUN']: + netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../solaris/JackSolarisTime.c'] + netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") + + + if bld.env['IS_MACOSX']: + netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../macosx/JackMachThread.cpp', '../macosx/JackMachTime.c'] + netlib.env.append_value("LINKFLAGS", "-framework CoreAudio -single_module") + + netlib.vnum = bld.env['JACK_API_VERSION'] + clientlib = bld.new_task_gen('cxx', 'shlib') clientlib.features.append('cc') clientlib.defines = 'HAVE_CONFIG_H' diff --git a/example-clients/netmaster.c b/example-clients/netmaster.c new file mode 100644 index 00000000..c00fbb35 --- /dev/null +++ b/example-clients/netmaster.c @@ -0,0 +1,181 @@ +/* + Copyright (C) 2009 Grame + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include +#include +#include + +#include + +jack_net_master_t* net; + +#define BUFFER_SIZE 512 +#define SAMPLE_RATE 44100 + +static void signal_handler(int sig) +{ + jack_net_master_close(net); + fprintf(stderr, "signal received, exiting ...\n"); + exit(0); +} + +static void +usage () +{ + fprintf (stderr, "\n" + "usage: jack_net_master \n" + " [ -b buffer size (default = %d) ]\n" + " [ -r sample rate (default = %d) ]\n" + " [ -a hostname (default = %s) ]\n" + " [ -p port (default = %d) ]\n", BUFFER_SIZE, SAMPLE_RATE, DEFAULT_MULTICAST_IP, DEFAULT_PORT); +} + +int +main (int argc, char *argv[]) +{ + int buffer_size = BUFFER_SIZE; + int sample_rate = SAMPLE_RATE; + int port = DEFAULT_PORT; + char* multicast_ip = DEFAULT_MULTICAST_IP; + const char *options = "b:r:a:p:"; + int option_index; + int opt; + + struct option long_options[] = + { + {"buffer size", 1, 0, 'b'}, + {"sample rate", 1, 0, 'r'}, + {"hostname", 1, 0, 'a'}, + {"port", 1, 0, 'p'}, + {0, 0, 0, 0} + }; + + while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { + + switch (opt) { + + case 'b': + buffer_size = atoi(optarg); + break; + + case 'r': + sample_rate = atoi(optarg); + break; + + case 'a': + multicast_ip = strdup(optarg); + break; + + case 'p': + port = atoi(optarg); + break; + + case 'h': + usage(); + return -1; + } + } + + int i; + jack_master_t request = { buffer_size, sample_rate, "master" }; + jack_slave_t result; + float** audio_input_buffer; + float** audio_output_buffer; + int wait_usec = (int) ((((float)buffer_size) * 1000000) / ((float)sample_rate)); + + printf("Waiting for a slave...\n"); + + if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_master", &request, &result)) == 0) { + fprintf(stderr, "jack server not running?\n"); + return 1; + } + + printf("Slave is running...\n"); + + /* install a signal handler to properly quits jack client */ +#ifdef WIN32 + signal(SIGINT, signal_handler); + signal(SIGABRT, signal_handler); + signal(SIGTERM, signal_handler); +#else + signal(SIGQUIT, signal_handler); + signal(SIGTERM, signal_handler); + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); +#endif + + // Allocate buffers + audio_input_buffer = calloc(result.audio_input, sizeof(float*)); + for (i = 0; i < result.audio_input; i++) { + audio_input_buffer[i] = calloc(buffer_size, sizeof(float)); + } + + audio_output_buffer = calloc(result.audio_output, sizeof(float*)); + for (i = 0; i < result.audio_output; i++) { + audio_output_buffer[i] = calloc(buffer_size, sizeof(float)); + } + + /* + Run until interrupted. + + WARNING !! : this code is given for demonstration purpose. For proper timing bevahiour + it has to be called in a real-time context (which is *not* the case here...) + */ + + while (1) { + + // Copy input to output + for (i = 0; i < result.audio_input; i++) { + memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); + } + + if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { + printf("jack_net_master_send failure, exiting\n"); + break; + } + + if (jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) { + printf("jack_net_master_recv failure, exiting\n"); + break; + } + + usleep(wait_usec); + }; + + // Wait for application end + jack_net_master_close(net); + + for (i = 0; i < result.audio_input; i++) { + free(audio_input_buffer[i]); + } + free(audio_input_buffer); + + for (i = 0; i < result.audio_output; i++) { + free(audio_output_buffer[i]); + } + free(audio_output_buffer); + + exit (0); +} diff --git a/example-clients/netslave.c b/example-clients/netslave.c new file mode 100644 index 00000000..446d1561 --- /dev/null +++ b/example-clients/netslave.c @@ -0,0 +1,168 @@ +/* + Copyright (C) 2009 Grame + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include +#include +#include + +#include + +jack_net_slave_t* net; + +static void signal_handler(int sig) +{ + jack_net_slave_close(net); + fprintf(stderr, "signal received, exiting ...\n"); + exit(0); +} + +static void +usage () +{ + fprintf (stderr, "\n" + "usage: jack_net_slave \n" + " [ -C capture channels (default = 2)]\n" + " [ -P playback channels (default = 2) ]\n" + " [ -a hostname (default = %s) ]\n" + " [ -p port (default = %d)]\n", DEFAULT_MULTICAST_IP, DEFAULT_PORT); +} + +static void net_shutdown(void* data) +{ + printf("Restarting...\n"); +} + +static int net_process(jack_nframes_t buffer_size, + int audio_input, + float** audio_input_buffer, + int midi_input, + void** midi_input_buffer, + int audio_output, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, + void* data) +{ + int i; + + // Copy input to output + for (i = 0; i < audio_input; i++) { + memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); + } + return 0; +} + +int +main (int argc, char *argv[]) +{ + int audio_input = 2; + int audio_output = 2; + int port = DEFAULT_PORT; + char* multicast_ip = DEFAULT_MULTICAST_IP; + const char *options = "C:P:a:p:"; + int option_index; + int opt; + + struct option long_options[] = + { + {"audio input", 1, 0, 'C'}, + {"audio output", 1, 0, 'P'}, + {"hostname", 1, 0, 'a'}, + {"port", 1, 0, 'p'}, + {0, 0, 0, 0} + }; + + while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { + + switch (opt) { + + case 'C': + audio_input = atoi(optarg); + break; + + case 'P': + audio_output = atoi(optarg); + break; + + case 'a': + multicast_ip = strdup(optarg); + break; + + case 'p': + port = atoi(optarg); + break; + + case 'h': + usage(); + return -1; + } + } + + jack_slave_t request = { audio_input, audio_output, 0, 0, DEFAULT_MTU, -1, JackSlowMode }; + jack_master_t result; + + printf("Waiting for a master...\n"); + + if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_slave", &request, &result)) == 0) { + fprintf(stderr, "jack server not running?\n"); + return 1; + } + + printf("Slave is found and running...\n"); + + jack_set_net_slave_process_callback(net, net_process, NULL); + jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL); + + if (jack_net_slave_activate(net) != 0) { + fprintf(stderr, "Cannot sactivate client\n"); + return 1; + } + + /* install a signal handler to properly quits jack client */ +#ifdef WIN32 + signal(SIGINT, signal_handler); + signal(SIGABRT, signal_handler); + signal(SIGTERM, signal_handler); +#else + signal(SIGQUIT, signal_handler); + signal(SIGTERM, signal_handler); + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); +#endif + + /* run until interrupted */ + while (1) { + #ifdef WIN32 + Sleep(1000); + #else + sleep(1); + #endif + }; + + // Wait for application end + jack_net_slave_deactivate(net); + jack_net_slave_close(net); + exit (0); +} diff --git a/example-clients/wscript b/example-clients/wscript index dcc13d08..9c70e27a 100644 --- a/example-clients/wscript +++ b/example-clients/wscript @@ -25,6 +25,8 @@ example_programs = { 'jack_simple_session_client' : 'simple_session_client.c', 'jack_session_notify' : 'session_notify.c', 'jack_server_control' : 'server_control.cpp', + 'jack_net_slave' : 'netslave.c', + 'jack_net_master' : 'netmaster.c', 'jack_latent_client' : 'latent_client.c', 'jack_midi_dump' : 'midi_dump.c', 'jack_midi_latency_test' : 'midi_latency_test.c' @@ -86,8 +88,13 @@ def build(bld): prog.env.append_value("LINKFLAGS", "-lm") if example_program == 'jack_server_control': prog.uselib_local = 'serverlib' + elif example_program == 'jack_net_slave': + prog.uselib_local = 'netlib' + elif example_program == 'jack_net_master': + prog.uselib_local = 'netlib' else: - prog.uselib_local = 'clientlib' + prog.uselib_local = 'clientlib' + prog.target = example_program if bld.env['BUILD_EXAMPLE_CLIENT_TRANSPORT']: diff --git a/macosx/JackMachThread.cpp b/macosx/JackMachThread.cpp index d17d0497..19f99b54 100644 --- a/macosx/JackMachThread.cpp +++ b/macosx/JackMachThread.cpp @@ -18,9 +18,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #include "JackMachThread.h" #include "JackError.h" +#include "/Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.h" + namespace Jack { @@ -30,11 +33,17 @@ int JackMachThread::SetThreadToPriority(jack_native_thread_t thread, UInt32 inPr // REAL-TIME / TIME-CONSTRAINT THREAD thread_time_constraint_policy_data_t theTCPolicy; +#ifdef MY_TARGET_OS_IPHONE + theTCPolicy.period = CAHostTimeBase::ConvertFromNanos(period); + theTCPolicy.computation = CAHostTimeBase::ConvertFromNanos(computation); + theTCPolicy.constraint = CAHostTimeBase::ConvertFromNanos(constraint); +#else theTCPolicy.period = AudioConvertNanosToHostTime(period); theTCPolicy.computation = AudioConvertNanosToHostTime(computation); theTCPolicy.constraint = AudioConvertNanosToHostTime(constraint); +#endif theTCPolicy.preemptible = true; - kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) & theTCPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT); + kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) &theTCPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT); jack_log("JackMachThread::thread_policy_set res = %ld", res); return (res == KERN_SUCCESS) ? 0 : -1; } else { @@ -57,7 +66,7 @@ int JackMachThread::SetThreadToPriority(jack_native_thread_t thread, UInt32 inPr relativePriority = inPriority - GetThreadSetPriority(pthread_self()); thePrecedencePolicy.importance = relativePriority; - kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) & thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); + kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) &thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); jack_log("JackMachThread::thread_policy_set res = %ld", res); return (res == KERN_SUCCESS) ? 0 : -1; } @@ -130,9 +139,16 @@ int JackMachThread::GetParams(jack_native_thread_t thread, UInt64* period, UInt6 &count, &get_default); if (res == KERN_SUCCESS) { + #ifdef MY_TARGET_OS_IPHONE + *period = CAHostTimeBase::ConvertToNanos(theTCPolicy.period); + *computation = CAHostTimeBase::ConvertToNanos(theTCPolicy.computation); + *constraint = CAHostTimeBase::ConvertToNanos(theTCPolicy.constraint); + #else *period = AudioConvertHostTimeToNanos(theTCPolicy.period); *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation); *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint); + #endif + jack_log("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld", long(*period / 1000.0f), long(*computation / 1000.0f), long(*constraint / 1000.0f)); return 0; } else { diff --git a/macosx/JackMachThread.h b/macosx/JackMachThread.h index 92f77d9e..bb9e18f0 100644 --- a/macosx/JackMachThread.h +++ b/macosx/JackMachThread.h @@ -61,12 +61,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __JackMachThread__ #define __JackMachThread__ +#include + +#ifdef MY_TARGET_OS_IPHONE +typedef unsigned char Boolean; +#endif + + #include "JackPosixThread.h" +#ifndef MY_TARGET_OS_IPHONE #include +#endif #include #include +#ifndef MY_TARGET_OS_IPHONE #include +#endif #define THREAD_SET_PRIORITY 0 #define THREAD_SCHEDULED_PRIORITY 1 diff --git a/macosx/JackPlatformPlug_os.h b/macosx/JackPlatformPlug_os.h index 3595803f..97eece1e 100644 --- a/macosx/JackPlatformPlug_os.h +++ b/macosx/JackPlatformPlug_os.h @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software +along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -20,25 +20,34 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __JackPlatformPlug_APPLE__ #define __JackPlatformPlug_APPLE__ +#include + #define jack_server_dir "/tmp" #define jack_client_dir "/tmp" #define JACK_DEFAULT_DRIVER "coreaudio" namespace Jack -{ +{ struct JackRequest; struct JackResult; - + class JackPosixMutex; class JackMachThread; class JackMachSemaphore; - + class JackSocketServerChannel; class JackSocketClientChannel; class JackSocketServerNotifyChannel; class JackSocketNotifyChannel; - + class JackNetUnixSocket; + +#ifdef MY_TARGET_OS_IPHONE + class JackClient; + class JackGraphManager; + class JackEngineControl; + class JackSynchro; +#endif } /* __JackPlatformMutex__ */ @@ -50,8 +59,13 @@ namespace Jack { typedef JackPosixMutex JackMutex; } namespace Jack { typedef JackMachThread JackThread; } /* __JackPlatformSynchro__ client activation */ +#ifndef MY_TARGET_OS_IPHONE #include "JackMachSemaphore.h" namespace Jack { typedef JackMachSemaphore JackSynchro; } +#endif + +#include "JackSocket.h" +namespace Jack { typedef JackClientSocket JackChannelTransaction; } #include "JackSocket.h" namespace Jack { typedef JackClientSocket JackChannelTransaction; } @@ -60,7 +74,8 @@ namespace Jack { typedef JackClientSocket JackChannelTransaction; } #include "JackProcessSync.h" /* Only on windows a special JackProcessSync is used. It is directly defined by including JackProcessSync.h here */ -/* __JackPlatformServerChannel__ */ +#ifndef MY_TARGET_OS_IPHONE +/* __JackPlatformServerChannel__ */ #include "JackSocketServerChannel.h" namespace Jack { typedef JackSocketServerChannel JackServerChannel; } @@ -75,6 +90,7 @@ namespace Jack { typedef JackSocketServerNotifyChannel JackServerNotifyChannel; /* __JackPlatformNotifyChannel__ */ #include "JackSocketNotifyChannel.h" namespace Jack { typedef JackSocketNotifyChannel JackNotifyChannel; } +#endif /* __JackPlatformNetSocket__ */ #include "JackNetUnixSocket.h" diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index eb5eb758..5961dd82 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -9506,6 +9506,7 @@ ); OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\""; OTHER_LDFLAGS = ( + libcelt.a, "-framework", Carbon, "-framework", @@ -9574,6 +9575,7 @@ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\""; OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DLIB_DIR=\\\"lib\\\""; OTHER_LDFLAGS = ( + libcelt.a, "-framework", Carbon, "-framework", diff --git a/macosx/coreaudio/JackCoreAudioAdapter.h b/macosx/coreaudio/JackCoreAudioAdapter.h index 8ef6e4d2..f002933f 100644 --- a/macosx/coreaudio/JackCoreAudioAdapter.h +++ b/macosx/coreaudio/JackCoreAudioAdapter.h @@ -136,7 +136,7 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface public: - JackCoreAudioAdapter( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); + JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); ~JackCoreAudioAdapter() {} diff --git a/macosx/coreaudio/TiPhoneCoreAudioRenderer.cpp b/macosx/coreaudio/TiPhoneCoreAudioRenderer.cpp new file mode 100644 index 00000000..d44a9899 --- /dev/null +++ b/macosx/coreaudio/TiPhoneCoreAudioRenderer.cpp @@ -0,0 +1,409 @@ +/* +Copyright (C) 2010 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "TiPhoneCoreAudioRenderer.h" + +static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) +{ + printf("- - - - - - - - - - - - - - - - - - - -\n"); + printf(" Sample Rate:%f\n", inDesc->mSampleRate); + printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID); + printf(" Format Flags:%lX\n", inDesc->mFormatFlags); + printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); + printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); + printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); + printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); + printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); + printf("- - - - - - - - - - - - - - - - - - - -\n"); +} + +static void printError(OSStatus err) +{ + switch (err) { + case kAudioConverterErr_FormatNotSupported: + printf("error code : kAudioConverterErr_FormatNotSupported\n"); + break; + case kAudioConverterErr_OperationNotSupported: + printf("error code : kAudioConverterErr_OperationNotSupported\n"); + break; + case kAudioConverterErr_PropertyNotSupported: + printf("error code : kAudioConverterErr_PropertyNotSupported\n"); + break; + case kAudioConverterErr_InvalidInputSize: + printf("error code : kAudioConverterErr_InvalidInputSize\n"); + break; + case kAudioConverterErr_InvalidOutputSize: + printf("error code : kAudioConverterErr_InvalidOutputSize\n"); + break; + case kAudioConverterErr_UnspecifiedError: + printf("error code : kAudioConverterErr_UnspecifiedError\n"); + break; + case kAudioConverterErr_BadPropertySizeError: + printf("error code : kAudioConverterErr_BadPropertySizeError\n"); + break; + case kAudioConverterErr_RequiresPacketDescriptionsError: + printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n"); + break; + case kAudioConverterErr_InputSampleRateOutOfRange: + printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n"); + break; + case kAudioConverterErr_OutputSampleRateOutOfRange: + printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n"); + break; + default: + printf("error code : unknown\n"); + break; + } +} + +OSStatus TiPhoneCoreAudioRenderer::Render(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32, + UInt32 inNumberFrames, + AudioBufferList *ioData) +{ + TiPhoneCoreAudioRendererPtr renderer = (TiPhoneCoreAudioRendererPtr)inRefCon; + AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, renderer->fCAInputData); + + float coef = float(LONG_MAX); + float inv_coef = 1.f/float(LONG_MAX); + + for (int chan = 0; chan < renderer->fDevNumInChans; chan++) { + for (int frame = 0; frame < inNumberFrames; frame++) { + renderer->fInChannel[chan][frame] = float(((int*)renderer->fCAInputData->mBuffers[chan].mData)[frame]) * inv_coef; + } + } + + renderer->PerformAudioCallback((int)inNumberFrames); + + for (int chan = 0; chan < renderer->fDevNumOutChans; chan++) { + for (int frame = 0; frame < inNumberFrames; frame++) { + ((int*)ioData->mBuffers[chan].mData)[frame] = int(renderer->fOutChannel[chan][frame] * coef); + } + } + + return 0; +} + +void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 inInterruption) +{ + TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData; + printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption"); + + if (inInterruption == kAudioSessionEndInterruption) { + // make sure we are again the active session + AudioSessionSetActive(true); + AudioOutputUnitStart(obj->fAUHAL); + } + + if (inInterruption == kAudioSessionBeginInterruption) { + AudioOutputUnitStop(obj->fAUHAL); + } +} + +int TiPhoneCoreAudioRenderer::Open(int bufferSize, int samplerate) +{ + OSStatus err1; + UInt32 outSize; + UInt32 enableIO; + AudioStreamBasicDescription srcFormat, dstFormat; + + printf("Open fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate); + + // Initialize and configure the audio session + err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); + if (err1 != noErr) { + printf("Couldn't initialize audio session\n"); + printError(err1); + return OPEN_ERR; + } + + err1 = AudioSessionSetActive(true); + if (err1 != noErr) { + printf("Couldn't set audio session active\n"); + printError(err1); + return OPEN_ERR; + } + + UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; + err1 = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); + if (err1 != noErr) { + printf("Couldn't set audio category\n"); + printError(err1); + return OPEN_ERR; + } + + //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener"); + + Float64 hwSampleRate; + outSize = sizeof(hwSampleRate); + err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate); + if (err1 != noErr) { + printf("Couldn't get hw sample rate\n"); + printError(err1); + return OPEN_ERR; + } else { + printf("Get hw sample rate %f\n", hwSampleRate); + } + + Float32 hwBufferSize; + outSize = sizeof(hwBufferSize); + err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize); + if (err1 != noErr) { + printf("Couldn't get hw buffer duration\n"); + printError(err1); + return OPEN_ERR; + } else { + printf("Get hw buffer duration %f\n", hwBufferSize); + } + + UInt32 hwInput; + outSize = sizeof(hwInput); + err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &hwInput); + if (err1 != noErr) { + printf("Couldn't get hw input channels\n"); + printError(err1); + return OPEN_ERR; + } else { + printf("Get hw input channels %d\n", hwInput); + } + + UInt32 hwOutput; + outSize = sizeof(hwOutput); + err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &hwOutput); + if (err1 != noErr) { + printf("Couldn't get hw output channels\n"); + printError(err1); + return OPEN_ERR; + } else { + printf("Get hw output channels %d\n", hwOutput); + } + + Float32 preferredBufferSize = float(bufferSize) / float(samplerate); + printf("preferredBufferSize %f \n", preferredBufferSize); + + err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize); + if (err1 != noErr) { + printf("Couldn't set i/o buffer duration\n"); + printError(err1); + return OPEN_ERR; + } + + Float64 preferredSamplerate = float(samplerate); + err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate); + if (err1 != noErr) { + printf("Couldn't set i/o sample rate\n"); + printError(err1); + return OPEN_ERR; + } + + // AUHAL + AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0}; + AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd); + + err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL); + if (err1 != noErr) { + printf("Error calling OpenAComponent\n"); + printError(err1); + goto error; + } + + enableIO = 1; + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n"); + printError(err1); + goto error; + } + + enableIO = 1; + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n"); + printError(err1); + goto error; + } + + UInt32 maxFPS; + outSize = sizeof(maxFPS); + err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize); + if (err1 != noErr) { + printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n"); + printError(err1); + goto error; + } else { + printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS); + } + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); + printError(err1); + goto error; + } + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); + printError(err1); + goto error; + } + + err1 = AudioUnitInitialize(fAUHAL); + if (err1 != noErr) { + printf("Cannot initialize AUHAL unit\n"); + printError(err1); + goto error; + } + + // Setting format + + if (fDevNumInChans > 0) { + outSize = sizeof(AudioStreamBasicDescription); + err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize); + if (err1 != noErr) { + printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); + printError(err1); + } + PrintStreamDesc(&srcFormat); + + srcFormat.mFormatID = kAudioFormatLinearPCM; + srcFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; + srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); + srcFormat.mFramesPerPacket = 1; + srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); + srcFormat.mChannelsPerFrame = fDevNumInChans; + srcFormat.mBitsPerChannel = 32; + + PrintStreamDesc(&srcFormat); + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); + printError(err1); + } + } + + if (fDevNumOutChans > 0) { + outSize = sizeof(AudioStreamBasicDescription); + err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize); + if (err1 != noErr) { + printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); + printError(err1); + } + PrintStreamDesc(&dstFormat); + + dstFormat.mFormatID = kAudioFormatLinearPCM; + dstFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; + dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); + dstFormat.mFramesPerPacket = 1; + dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); + dstFormat.mChannelsPerFrame = fDevNumOutChans; + dstFormat.mBitsPerChannel = 32; + + PrintStreamDesc(&dstFormat); + + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); + printError(err1); + } + } + + if (fDevNumInChans > 0 && fDevNumOutChans == 0) { + AURenderCallbackStruct output; + output.inputProc = Render; + output.inputProcRefCon = this; + err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); + printError(err1); + goto error; + } + } else { + AURenderCallbackStruct output; + output.inputProc = Render; + output.inputProcRefCon = this; + err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output)); + if (err1 != noErr) { + printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); + printError(err1); + goto error; + } + } + + // Prepare buffers + fCAInputData = (AudioBufferList*)malloc(sizeof(UInt32) + fDevNumInChans * sizeof(AudioBuffer)); + fCAInputData->mNumberBuffers = fDevNumInChans; + for (int i = 0; i < fDevNumInChans; i++) { + fCAInputData->mBuffers[i].mNumberChannels = 1; + fCAInputData->mBuffers[i].mDataByteSize = bufferSize * sizeof(int); + fCAInputData->mBuffers[i].mData = malloc(bufferSize * sizeof(int)); + } + + /* + // Add listeners + err1 = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this); + if (err != noErr) { + jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload"); + printError(err); + return -1; + } + */ + + return NO_ERR; + +error: + AudioUnitUninitialize(fAUHAL); + AudioComponentInstanceDispose(fAUHAL); + return OPEN_ERR; +} + +int TiPhoneCoreAudioRenderer::Close() +{ + AudioUnitUninitialize(fAUHAL); + AudioComponentInstanceDispose(fAUHAL); + return NO_ERR; +} + +int TiPhoneCoreAudioRenderer::Start() +{ + AudioSessionSetActive(true); + OSStatus err = AudioOutputUnitStart(fAUHAL); + + if (err != noErr) { + printf("Error while opening device : device open error \n"); + return OPEN_ERR; + } else { + return NO_ERR; + } +} + +int TiPhoneCoreAudioRenderer::Stop() +{ + OSStatus err = AudioOutputUnitStop(fAUHAL); + + if (err != noErr) { + printf("Error while closing device : device close error \n"); + return OPEN_ERR; + } else { + return NO_ERR; + } +} diff --git a/macosx/coreaudio/TiPhoneCoreAudioRenderer.h b/macosx/coreaudio/TiPhoneCoreAudioRenderer.h new file mode 100644 index 00000000..a5c47ab7 --- /dev/null +++ b/macosx/coreaudio/TiPhoneCoreAudioRenderer.h @@ -0,0 +1,116 @@ +/* +Copyright (C) 2010 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __TiPhoneCoreAudioRenderer__ +#define __TiPhoneCoreAudioRenderer__ + +#include +#include +#include + +#define MAX_CHANNELS 256 +#define OPEN_ERR -1 +#define NO_ERR 0 + +typedef void (*AudioCallback) (int frames, float** inputs, float** outputs, void* arg); + +class TiPhoneCoreAudioRenderer +{ + + private: + + AudioUnit fAUHAL; + AudioCallback fAudioCallback; + void* fCallbackArg; + + int fDevNumInChans; + int fDevNumOutChans; + + AudioBufferList* fCAInputData; + + float* fInChannel[MAX_CHANNELS]; + float* fOutChannel[MAX_CHANNELS]; + + static OSStatus Render(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData); + + static void InterruptionListener(void *inClientData, UInt32 inInterruption); + + public: + + TiPhoneCoreAudioRenderer(int input, int output) + :fAudioCallback(NULL), fCallbackArg(NULL), fDevNumInChans(input), fDevNumOutChans(output), fCAInputData(NULL) + { + memset(fInChannel, 0, sizeof(float*) * MAX_CHANNELS); + memset(fOutChannel, 0, sizeof(float*) * MAX_CHANNELS); + + for (int i = 0; i < fDevNumInChans; i++) { + fInChannel[i] = new float[8192]; + } + + for (int i = 0; i < fDevNumOutChans; i++) { + fOutChannel[i] = new float[8192]; + } + } + + virtual ~TiPhoneCoreAudioRenderer() + { + for (int i = 0; i < fDevNumInChans; i++) { + delete[] fInChannel[i]; + } + + for (int i = 0; i < fDevNumOutChans; i++) { + delete[] fOutChannel[i]; + } + + if (fCAInputData) { + for (int i = 0; i < fDevNumInChans; i++) { + free(fCAInputData->mBuffers[i].mData); + } + free(fCAInputData); + } + } + + int Open(int bufferSize, int sampleRate); + int Close(); + + int Start(); + int Stop(); + + void SetAudioCallback(AudioCallback callback, void* arg) + { + fAudioCallback = callback; + fCallbackArg = arg; + } + + void PerformAudioCallback(int frames) + { + if (fAudioCallback) + fAudioCallback(frames, fInChannel, fOutChannel, fCallbackArg); + } + +}; + +typedef TiPhoneCoreAudioRenderer * TiPhoneCoreAudioRendererPtr; + +#endif diff --git a/macosx/iphone/Info.plist b/macosx/iphone/Info.plist new file mode 100644 index 00000000..38cb25cf --- /dev/null +++ b/macosx/iphone/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + fr.grame.iGrame.iPhoneFaustNet + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + + diff --git a/macosx/iphone/MainWindow.xib b/macosx/iphone/MainWindow.xib new file mode 100644 index 00000000..a36742fe --- /dev/null +++ b/macosx/iphone/MainWindow.xib @@ -0,0 +1,440 @@ + + + + 528 + 10C540 + 740 + 1038.25 + 458.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 62 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + + + IBFirstResponder + + + + + 1316 + + YES + + + 1316 + {{25, 40}, {267, 21}} + + NO + YES + NO + NetJack : client on JACK server + + Helvetica-Bold + 17 + 16 + + + 1 + MCAwIDAAA + + + 1 + 10 + + + + {320, 480} + + + 1 + MSAxIDEAA + + NO + NO + + + + + + YES + + + delegate + + + + 4 + + + + window + + + + 5 + + + + + YES + + 0 + + + + + + 2 + + + YES + + + + + + -1 + + + File's Owner + + + 3 + + + + + -2 + + + + + 10 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 10.IBPluginDependency + 2.IBAttributePlaceholdersKey + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + 2.IBUserGuides + 3.CustomClassName + 3.IBPluginDependency + + + YES + UIApplication + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + YES + + + YES + + + {{366, 320}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + YES + + + 153.5 + 0 + + + iPhoneNetAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 11 + + + + YES + + iPhoneNetAppDelegate + NSObject + + YES + + YES + navigationController + window + + + YES + UINavigationController + UIWindow + + + + IBProjectSource + iPhoneNetAppDelegate.h + + + + iPhoneNetAppDelegate + NSObject + + IBUserSource + + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UILabel + UIView + + IBFrameworkSource + UIKit.framework/Headers/UILabel.h + + + + UINavigationController + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIResponder + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + iPhoneNet.xcodeproj + 3 + 3.1 + + diff --git a/macosx/iphone/freeverb.mm b/macosx/iphone/freeverb.mm new file mode 100644 index 00000000..3daabc9a --- /dev/null +++ b/macosx/iphone/freeverb.mm @@ -0,0 +1,754 @@ +//----------------------------------------------------- +// name: "freeverb" +// version: "1.0" +// author: "Grame" +// license: "BSD" +// copyright: "(c)GRAME 2006" +// +// Code generated with Faust 0.9.9.5b2 (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ + +/* link with */ +#include +/* link with */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "JackAudioQueueAdapter.h" + +using namespace std; + +// On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero) +// flags to avoid costly denormals +#ifdef __SSE__ + #include + #ifdef __SSE2__ + #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040) + #else + #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000) + #endif +#else + #define AVOIDDENORMALS +#endif + +//#define BENCHMARKMODE + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); } +inline int int2pow2 (int x) { int r=0; while ((1< fPrefix; + map fKeyParam; + + void addOption(const char* label, float* zone, float min, float max) + { + string fullname = fPrefix.top() + label; + fKeyParam.insert(make_pair(fullname, param(zone, min, max))); + } + + void openAnyBox(const char* label) + { + string prefix; + + if (label && label[0]) { + prefix = fPrefix.top() + "-" + label; + } else { + prefix = fPrefix.top(); + } + fPrefix.push(prefix); + } + +public: + + CMDUI(int argc, char *argv[]) : UI(), fArgc(argc), fArgv(argv) { fPrefix.push("--"); } + virtual ~CMDUI() {} + + virtual void addButton(const char* label, float* zone) {}; + virtual void addToggleButton(const char* label, float* zone) {}; + virtual void addCheckButton(const char* label, float* zone) {}; + + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) + { + addOption(label,zone,min,max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) + { + addOption(label,zone,min,max); + } + + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) + { + addOption(label,zone,min,max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) {} + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) {} + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {} + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) {} + + virtual void openFrameBox(const char* label) { openAnyBox(label); } + virtual void openTabBox(const char* label) { openAnyBox(label); } + virtual void openHorizontalBox(const char* label) { openAnyBox(label); } + virtual void openVerticalBox(const char* label) { openAnyBox(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() + { + char c; + printf("Type 'q' to quit\n"); + while ((c = getchar()) != 'q') { + sleep(1); + } + } + + void print() + { + map::iterator i; + cout << fArgc << "\n"; + cout << fArgv[0] << " option list : "; + for (i = fKeyParam.begin(); i != fKeyParam.end(); i++) { + cout << "[ " << i->first << " " << i->second.fMin << ".." << i->second.fMax <<" ] "; + } + } + + void process_command() + { + map::iterator p; + for (int i = 1; i < fArgc; i++) { + if (fArgv[i][0] == '-') { + p = fKeyParam.find(fArgv[i]); + if (p == fKeyParam.end()) { + cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n"; + print(); + exit(1); + } + char* end; + *(p->second.fZone) = float(strtod(fArgv[i+1], &end)); + i++; + } + } + } + + void process_init() + { + map::iterator p; + for (int i = 1; i < fArgc; i++) { + if (fArgv[i][0] == '-') { + p = fKeyParam.find(fArgv[i]); + if (p == fKeyParam.end()) { + cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n"; + exit(1); + } + char* end; + *(p->second.fZone) = float(strtod(fArgv[i+1], &end)); + i++; + } + } + } +}; + + +//---------------------------------------------------------------- +// Signal processor definition +//---------------------------------------------------------------- + +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; + virtual void conclude() {} +}; + + +//---------------------------------------------------------------------------- +// FAUST generated code +//---------------------------------------------------------------------------- + + +class mydsp : public dsp { + private: + float fslider0; + float fRec9[2]; + float fslider1; + int IOTA; + float fVec0[2048]; + float fRec8[2]; + float fRec11[2]; + float fVec1[2048]; + float fRec10[2]; + float fRec13[2]; + float fVec2[2048]; + float fRec12[2]; + float fRec15[2]; + float fVec3[2048]; + float fRec14[2]; + float fRec17[2]; + float fVec4[2048]; + float fRec16[2]; + float fRec19[2]; + float fVec5[2048]; + float fRec18[2]; + float fRec21[2]; + float fVec6[2048]; + float fRec20[2]; + float fRec23[2]; + float fVec7[2048]; + float fRec22[2]; + float fVec8[1024]; + float fRec6[2]; + float fVec9[512]; + float fRec4[2]; + float fVec10[512]; + float fRec2[2]; + float fVec11[256]; + float fRec0[2]; + float fslider2; + float fRec33[2]; + float fVec12[2048]; + float fRec32[2]; + float fRec35[2]; + float fVec13[2048]; + float fRec34[2]; + float fRec37[2]; + float fVec14[2048]; + float fRec36[2]; + float fRec39[2]; + float fVec15[2048]; + float fRec38[2]; + float fRec41[2]; + float fVec16[2048]; + float fRec40[2]; + float fRec43[2]; + float fVec17[2048]; + float fRec42[2]; + float fRec45[2]; + float fVec18[2048]; + float fRec44[2]; + float fRec47[2]; + float fVec19[2048]; + float fRec46[2]; + float fVec20[1024]; + float fRec30[2]; + float fVec21[512]; + float fRec28[2]; + float fVec22[512]; + float fRec26[2]; + float fVec23[256]; + float fRec24[2]; + public: + static void metadata(Meta* m) { + m->declare("name", "freeverb"); + m->declare("version", "1.0"); + m->declare("author", "Grame"); + m->declare("license", "BSD"); + m->declare("copyright", "(c)GRAME 2006"); + } + + virtual int getNumInputs() { return 2; } + virtual int getNumOutputs() { return 2; } + static void classInit(int samplingFreq) { + } + virtual void instanceInit(int samplingFreq) { + fSamplingFreq = samplingFreq; + fslider0 = 0.5f; + for (int i=0; i<2; i++) fRec9[i] = 0; + fslider1 = 0.8f; + IOTA = 0; + for (int i=0; i<2048; i++) fVec0[i] = 0; + for (int i=0; i<2; i++) fRec8[i] = 0; + for (int i=0; i<2; i++) fRec11[i] = 0; + for (int i=0; i<2048; i++) fVec1[i] = 0; + for (int i=0; i<2; i++) fRec10[i] = 0; + for (int i=0; i<2; i++) fRec13[i] = 0; + for (int i=0; i<2048; i++) fVec2[i] = 0; + for (int i=0; i<2; i++) fRec12[i] = 0; + for (int i=0; i<2; i++) fRec15[i] = 0; + for (int i=0; i<2048; i++) fVec3[i] = 0; + for (int i=0; i<2; i++) fRec14[i] = 0; + for (int i=0; i<2; i++) fRec17[i] = 0; + for (int i=0; i<2048; i++) fVec4[i] = 0; + for (int i=0; i<2; i++) fRec16[i] = 0; + for (int i=0; i<2; i++) fRec19[i] = 0; + for (int i=0; i<2048; i++) fVec5[i] = 0; + for (int i=0; i<2; i++) fRec18[i] = 0; + for (int i=0; i<2; i++) fRec21[i] = 0; + for (int i=0; i<2048; i++) fVec6[i] = 0; + for (int i=0; i<2; i++) fRec20[i] = 0; + for (int i=0; i<2; i++) fRec23[i] = 0; + for (int i=0; i<2048; i++) fVec7[i] = 0; + for (int i=0; i<2; i++) fRec22[i] = 0; + for (int i=0; i<1024; i++) fVec8[i] = 0; + for (int i=0; i<2; i++) fRec6[i] = 0; + for (int i=0; i<512; i++) fVec9[i] = 0; + for (int i=0; i<2; i++) fRec4[i] = 0; + for (int i=0; i<512; i++) fVec10[i] = 0; + for (int i=0; i<2; i++) fRec2[i] = 0; + for (int i=0; i<256; i++) fVec11[i] = 0; + for (int i=0; i<2; i++) fRec0[i] = 0; + fslider2 = 0.8f; + for (int i=0; i<2; i++) fRec33[i] = 0; + for (int i=0; i<2048; i++) fVec12[i] = 0; + for (int i=0; i<2; i++) fRec32[i] = 0; + for (int i=0; i<2; i++) fRec35[i] = 0; + for (int i=0; i<2048; i++) fVec13[i] = 0; + for (int i=0; i<2; i++) fRec34[i] = 0; + for (int i=0; i<2; i++) fRec37[i] = 0; + for (int i=0; i<2048; i++) fVec14[i] = 0; + for (int i=0; i<2; i++) fRec36[i] = 0; + for (int i=0; i<2; i++) fRec39[i] = 0; + for (int i=0; i<2048; i++) fVec15[i] = 0; + for (int i=0; i<2; i++) fRec38[i] = 0; + for (int i=0; i<2; i++) fRec41[i] = 0; + for (int i=0; i<2048; i++) fVec16[i] = 0; + for (int i=0; i<2; i++) fRec40[i] = 0; + for (int i=0; i<2; i++) fRec43[i] = 0; + for (int i=0; i<2048; i++) fVec17[i] = 0; + for (int i=0; i<2; i++) fRec42[i] = 0; + for (int i=0; i<2; i++) fRec45[i] = 0; + for (int i=0; i<2048; i++) fVec18[i] = 0; + for (int i=0; i<2; i++) fRec44[i] = 0; + for (int i=0; i<2; i++) fRec47[i] = 0; + for (int i=0; i<2048; i++) fVec19[i] = 0; + for (int i=0; i<2; i++) fRec46[i] = 0; + for (int i=0; i<1024; i++) fVec20[i] = 0; + for (int i=0; i<2; i++) fRec30[i] = 0; + for (int i=0; i<512; i++) fVec21[i] = 0; + for (int i=0; i<2; i++) fRec28[i] = 0; + for (int i=0; i<512; i++) fVec22[i] = 0; + for (int i=0; i<2; i++) fRec26[i] = 0; + for (int i=0; i<256; i++) fVec23[i] = 0; + for (int i=0; i<2; i++) fRec24[i] = 0; + } + virtual void init(int samplingFreq) { + classInit(samplingFreq); + instanceInit(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openVerticalBox("Freeverb"); + interface->addHorizontalSlider("Damp", &fslider0, 0.5f, 0.0f, 1.0f, 2.500000e-02f); + interface->addHorizontalSlider("RoomSize", &fslider1, 0.8f, 0.0f, 1.0f, 2.500000e-02f); + interface->addHorizontalSlider("Wet", &fslider2, 0.8f, 0.0f, 1.0f, 2.500000e-02f); + interface->closeBox(); + } + virtual void compute (int count, float** input, float** output) { + float fSlow0 = (0.4f * fslider0); + float fSlow1 = (1 - fSlow0); + float fSlow2 = (0.7f + (0.28f * fslider1)); + float fSlow3 = fslider2; + float fSlow4 = (1 - fSlow3); + float* input0 = input[0]; + float* input1 = input[1]; + float* output0 = output[0]; + float* output1 = output[1]; + for (int i=0; ihi) hi = m; + tot += m; + } + cout << low << ' ' << tot/(mesure-KSKIP) << ' ' << hi << endl; + + } else { + + for (int i = KSKIP+1; ihi) hi = m; + tot += m; + } + cout << low << ' ' << tot/(KMESURE-KSKIP) << ' ' << hi << endl; + + } +} + +#else + +#define STARTMESURE +#define STOPMESURE + +#endif + +static int net_process(jack_nframes_t buffer_size, + int audio_input, + float** audio_input_buffer, + int midi_input, + void** midi_input_buffer, + int audio_output, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, + void* data) +{ + AVOIDDENORMALS; + STARTMESURE + DSP.compute(buffer_size, audio_input_buffer, audio_output_buffer); + STOPMESURE + return 0; +} + +/****************************************************************************** +******************************************************************************* + + MAIN PLAY THREAD + +******************************************************************************* +*******************************************************************************/ + +//------------------------------------------------------------------------- +// MAIN +//------------------------------------------------------------------------- + + +#define TEST_MASTER "194.5.49.5" + +int main(int argc, char *argv[]) { + + UI* interface = new CMDUI(argc, argv); + jack_net_slave_t* net; + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + //Jack::JackAudioQueueAdapter audio(2, 2, 1024, 44100, NULL); + + gNumInChans = DSP.getNumInputs(); + gNumOutChans = DSP.getNumOutputs(); + + jack_slave_t request = { gNumInChans, gNumOutChans, 0, 0, DEFAULT_MTU, -1, JackSlowMode }; + jack_master_t result; + + printf("Network\n"); + + //if (audio.Open() < 0) { + // fprintf(stderr, "Cannot open audio\n"); + // return 1; + //} + + //audio.Start(); + + // Hang around forever... + //while(1) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); + + if ((net = jack_net_slave_open(TEST_MASTER, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { + fprintf(stderr, "jack remote server not running ?\n"); + return 1; + } + + jack_set_net_slave_process_callback(net, net_process, NULL); + + // We want to restart (that is "wait for available master" again) + //jack_set_net_shutdown_callback(net, net_shutdown, 0); + + DSP.init(result.sample_rate); + DSP.buildUserInterface(interface); + + if (jack_net_slave_activate(net) != 0) { + fprintf(stderr, "cannot activate net"); + return 1; + } + + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + + // Wait for application end + jack_net_slave_deactivate(net); + jack_net_slave_close(net); + + //if (audio.Close() < 0) { + // fprintf(stderr, "Cannot close audio\n"); + //} + + return retVal; +} diff --git a/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj b/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj new file mode 100755 index 00000000..eff06935 --- /dev/null +++ b/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj @@ -0,0 +1,1291 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 4B0772210F54018C000DC657 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 4B0772240F54018C000DC657 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; + 4B0772250F54018C000DC657 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; + 4B0772260F54018C000DC657 /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; }; + 4B0772270F54018C000DC657 /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; }; + 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; + 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; + 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; + 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; + 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; + 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; + 4B0772310F54018C000DC657 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 4B0772320F54018C000DC657 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 4B0772330F54018C000DC657 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 4B0772340F54018C000DC657 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; + 4B07724A0F54021B000DC657 /* main_slave.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B0772490F54021B000DC657 /* main_slave.mm */; }; + 4B0773860F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; }; + 4B0773870F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; }; + 4B0773880F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; }; + 4B1A94140F49BE2C00D3626B /* iPhoneNet_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 32CA4F630368D1EE00C91783 /* iPhoneNet_Prefix.pch */; }; + 4B1A94150F49BE2F00D3626B /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; + 4B1A94160F49BE3000D3626B /* JackMachThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B1A93540F49ACFC00D3626B /* JackMachThread.h */; }; + 4B1A94170F49BE3100D3626B /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; + 4B1A94180F49BE3100D3626B /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; }; + 4B1A94190F49BE3300D3626B /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; }; + 4B1A941A0F49BE3300D3626B /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; + 4B1A941B0F49BE3400D3626B /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; + 4B1A941C0F49BE3500D3626B /* JackNetUnixSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B1A93520F49ACF300D3626B /* JackNetUnixSocket.h */; }; + 4B1A941D0F49BE3500D3626B /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; + 4B1A941E0F49BE3600D3626B /* JackPosixThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B1A933C0F49AC4500D3626B /* JackPosixThread.h */; }; + 4B1A94540F49C03300D3626B /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; + 4B1A94550F49C03300D3626B /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; + 4B1A94560F49C03400D3626B /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; }; + 4B1A94570F49C03500D3626B /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; }; + 4B1A94580F49C03600D3626B /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; + 4B1A94590F49C03600D3626B /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; + 4B1A945A0F49C03600D3626B /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; + 4B1A95760F49CEAB00D3626B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; + 4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; + 4B2791890F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; + 4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; + 4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; + 4B41469810BD3C4300C12F0C /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 4B41469A10BD3C4300C12F0C /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; + 4B41469B10BD3C4300C12F0C /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; + 4B41469C10BD3C4300C12F0C /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; }; + 4B41469D10BD3C4300C12F0C /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; }; + 4B41469E10BD3C4300C12F0C /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; + 4B41469F10BD3C4300C12F0C /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; + 4B4146A010BD3C4300C12F0C /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; + 4B4146A210BD3C4300C12F0C /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; + 4B4146A310BD3C4300C12F0C /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; + 4B4146A410BD3C4300C12F0C /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; + 4B4146A510BD3C4300C12F0C /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; }; + 4B4146A610BD3C4300C12F0C /* freeverb.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDC8F90F5420C000465F9C /* freeverb.mm */; }; + 4B4146A710BD3C4300C12F0C /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; + 4B4146A910BD3C4300C12F0C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 4B4146AA10BD3C4300C12F0C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 4B4146AB10BD3C4300C12F0C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 4B4146AC10BD3C4300C12F0C /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; + 4B6B712C114BAE9A00ED9788 /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4B9CB1371136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB1381136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB1391136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB13A1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB13B1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB13C1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDC8F90F5420C000465F9C /* freeverb.mm */; }; + 4BC9C1F71135AB2800D22670 /* main_master.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B0772500F54022D000DC657 /* main_master.mm */; }; + 4BCB37B6112D647C008C7BC1 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 4BCB37C7112D647C008C7BC1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 4BCB37C8112D647C008C7BC1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 4BCB37C9112D647C008C7BC1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 4BCB37CA112D647C008C7BC1 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; + 4BCB37D9112D64D8008C7BC1 /* iphone-faust.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */; }; + 4BCF75DA10BC2FD90082C526 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 4BCF75DC10BC2FD90082C526 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; + 4BCF75DD10BC2FD90082C526 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; + 4BCF75DE10BC2FD90082C526 /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; }; + 4BCF75DF10BC2FD90082C526 /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; }; + 4BCF75E010BC2FD90082C526 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; + 4BCF75E110BC2FD90082C526 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; + 4BCF75E210BC2FD90082C526 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; + 4BCF75E410BC2FD90082C526 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; + 4BCF75E510BC2FD90082C526 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; + 4BCF75E610BC2FD90082C526 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; + 4BCF75E710BC2FD90082C526 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; }; + 4BCF75E910BC2FD90082C526 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; }; + 4BCF75EB10BC2FD90082C526 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 4BCF75EC10BC2FD90082C526 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 4BCF75ED10BC2FD90082C526 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 4BCF75EE10BC2FD90082C526 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; + 4BCF75F710BC30140082C526 /* audio_thru.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF75F610BC30140082C526 /* audio_thru.mm */; }; + 4BDFCD3D113DB6B700D77992 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 4BDFCD3E113DB6B700D77992 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4BDFCD4A113DB6B700D77992 /* main_slave.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B0772490F54021B000DC657 /* main_slave.mm */; }; + 4BDFCD4B113DB6B700D77992 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; }; + 4BDFCD4D113DB6B700D77992 /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4BDFCD4E113DB6B700D77992 /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; + 4BDFCD50113DB6B700D77992 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 4BDFCD51113DB6B700D77992 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 4BDFCD52113DB6B700D77992 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 4BDFCD53113DB6B700D77992 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; + 4BF1360F0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; + 4BF136100F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; + 4BF136130F4B0B5E00218A3F /* JackAudioAdapterInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */; }; + 4BF1364D0F4B0F7700218A3F /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; + 4BF1364E0F4B0F7700218A3F /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; + 4BF1364F0F4B0F7700218A3F /* JackResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF1364C0F4B0F7700218A3F /* JackResampler.h */; }; + 4BF136550F4B0F9F00218A3F /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; + 4BF136560F4B0F9F00218A3F /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; + 4BF15E2511356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4BF15E2611356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4BF15E2711356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; + 4BF15F7811357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; + 4BF15F7911357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; + 4BF15F7A11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; + 4BF15F7B11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; + 4BF15F7C11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; + 4BF15F7D11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; + 4BFF45600F4D5D9700106083 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; + 4BFF45630F4D5D9700106083 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; + 4BFF45640F4D5D9700106083 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; + 4BFF45650F4D5D9700106083 /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; }; + 4BFF45660F4D5D9700106083 /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; }; + 4BFF45670F4D5D9700106083 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; + 4BFF45680F4D5D9700106083 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; + 4BFF45690F4D5D9700106083 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; + 4BFF456B0F4D5D9700106083 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; + 4BFF456C0F4D5D9700106083 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; + 4BFF456D0F4D5D9700106083 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; + 4BFF45700F4D5D9700106083 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 4BFF45710F4D5D9700106083 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 4BFF45720F4D5D9700106083 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 4BFF45730F4D5D9700106083 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D6058910D05DD3D006BFB54 /* NetJackSlave.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetJackSlave.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* iPhoneNet_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iPhoneNet_Prefix.pch; sourceTree = ""; }; + 4B0772380F54018C000DC657 /* NetJackMaster.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetJackMaster.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B0772490F54021B000DC657 /* main_slave.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main_slave.mm; sourceTree = SOURCE_ROOT; }; + 4B0772500F54022D000DC657 /* main_master.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main_master.mm; sourceTree = SOURCE_ROOT; }; + 4B0773840F541EE2000DC657 /* iPhoneNetAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iPhoneNetAppDelegate.h; sourceTree = ""; }; + 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iPhoneNetAppDelegate.m; sourceTree = ""; }; + 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetAPI.cpp; path = ../../common/JackNetAPI.cpp; sourceTree = SOURCE_ROOT; }; + 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetInterface.cpp; path = ../../common/JackNetInterface.cpp; sourceTree = SOURCE_ROOT; }; + 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetTool.cpp; path = ../../common/JackNetTool.cpp; sourceTree = SOURCE_ROOT; }; + 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackPosixThread.cpp; path = ../../posix/JackPosixThread.cpp; sourceTree = SOURCE_ROOT; }; + 4B1A933C0F49AC4500D3626B /* JackPosixThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackPosixThread.h; path = ../../posix/JackPosixThread.h; sourceTree = SOURCE_ROOT; }; + 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetUnixSocket.cpp; path = ../../posix/JackNetUnixSocket.cpp; sourceTree = SOURCE_ROOT; }; + 4B1A93520F49ACF300D3626B /* JackNetUnixSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackNetUnixSocket.h; path = ../../posix/JackNetUnixSocket.h; sourceTree = SOURCE_ROOT; }; + 4B1A93540F49ACFC00D3626B /* JackMachThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMachThread.h; path = ../JackMachThread.h; sourceTree = SOURCE_ROOT; }; + 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMachThread.cpp; path = ../JackMachThread.cpp; sourceTree = SOURCE_ROOT; }; + 4B1A93870F49B0E300D3626B /* JackMachTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = JackMachTime.c; path = ../JackMachTime.c; sourceTree = SOURCE_ROOT; }; + 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; + 4B2791870F72570C000536B7 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; }; + 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B9CB1361136CA99007DE01A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = SOURCE_ROOT; }; + 4BBDC8F90F5420C000465F9C /* freeverb.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = freeverb.mm; sourceTree = SOURCE_ROOT; }; + 4BC9C1D31135AA1800D22670 /* iPhoneNetMasterAppl-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iPhoneNetMasterAppl-Info.plist"; sourceTree = ""; }; + 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaust.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "iphone-faust.mm"; sourceTree = SOURCE_ROOT; }; + 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneThruNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BCF75F610BC30140082C526 /* audio_thru.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = audio_thru.mm; sourceTree = SOURCE_ROOT; }; + 4BDFCD57113DB6B700D77992 /* NetJackSlave.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetJackSlave.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapterInterface.cpp; path = ../../common/JackAudioAdapterInterface.cpp; sourceTree = SOURCE_ROOT; }; + 4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAudioAdapterInterface.h; path = ../../common/JackAudioAdapterInterface.h; sourceTree = SOURCE_ROOT; }; + 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackResampler.cpp; path = ../../common/JackResampler.cpp; sourceTree = SOURCE_ROOT; }; + 4BF1364C0F4B0F7700218A3F /* JackResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackResampler.h; path = ../../common/JackResampler.h; sourceTree = SOURCE_ROOT; }; + 4BF136540F4B0F9F00218A3F /* ringbuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ringbuffer.c; path = ../../common/ringbuffer.c; sourceTree = SOURCE_ROOT; }; + 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CAHostTimeBase.cpp; path = /Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.cpp; sourceTree = ""; }; + 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TiPhoneCoreAudioRenderer.cpp; path = ../coreaudio/TiPhoneCoreAudioRenderer.cpp; sourceTree = SOURCE_ROOT; }; + 4BFF45120F4D59DB00106083 /* libjacknet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjacknet.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, + 4B1A95760F49CEAB00D3626B /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B0772300F54018C000DC657 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B0772310F54018C000DC657 /* Foundation.framework in Frameworks */, + 4B0772320F54018C000DC657 /* UIKit.framework in Frameworks */, + 4B0772330F54018C000DC657 /* CoreGraphics.framework in Frameworks */, + 4B0772340F54018C000DC657 /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B1A940E0F49BDE000D3626B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B4146A810BD3C4300C12F0C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B4146A910BD3C4300C12F0C /* Foundation.framework in Frameworks */, + 4B4146AA10BD3C4300C12F0C /* UIKit.framework in Frameworks */, + 4B4146AB10BD3C4300C12F0C /* CoreGraphics.framework in Frameworks */, + 4B4146AC10BD3C4300C12F0C /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BCB37C6112D647C008C7BC1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BCB37C7112D647C008C7BC1 /* Foundation.framework in Frameworks */, + 4BCB37C8112D647C008C7BC1 /* UIKit.framework in Frameworks */, + 4BCB37C9112D647C008C7BC1 /* CoreGraphics.framework in Frameworks */, + 4BCB37CA112D647C008C7BC1 /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BCF75EA10BC2FD90082C526 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BCF75EB10BC2FD90082C526 /* Foundation.framework in Frameworks */, + 4BCF75EC10BC2FD90082C526 /* UIKit.framework in Frameworks */, + 4BCF75ED10BC2FD90082C526 /* CoreGraphics.framework in Frameworks */, + 4BCF75EE10BC2FD90082C526 /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BDFCD4F113DB6B700D77992 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BDFCD50113DB6B700D77992 /* Foundation.framework in Frameworks */, + 4BDFCD51113DB6B700D77992 /* UIKit.framework in Frameworks */, + 4BDFCD52113DB6B700D77992 /* CoreGraphics.framework in Frameworks */, + 4BDFCD53113DB6B700D77992 /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BFF456F0F4D5D9700106083 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BFF45700F4D5D9700106083 /* Foundation.framework in Frameworks */, + 4BFF45710F4D5D9700106083 /* UIKit.framework in Frameworks */, + 4BFF45720F4D5D9700106083 /* CoreGraphics.framework in Frameworks */, + 4BFF45730F4D5D9700106083 /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* NetJackSlave.app */, + 4BFF45120F4D59DB00106083 /* libjacknet.a */, + 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */, + 4B0772380F54018C000DC657 /* NetJackMaster.app */, + 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */, + 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */, + 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */, + 4BDFCD57113DB6B700D77992 /* NetJackSlave.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */, + 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */, + 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 29B97317FDCFA39411CA2CEA /* Resources */, + 4BCF75F610BC30140082C526 /* audio_thru.mm */, + 4BBDC8F90F5420C000465F9C /* freeverb.mm */, + 4B0773840F541EE2000DC657 /* iPhoneNetAppDelegate.h */, + 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */, + 4BF136540F4B0F9F00218A3F /* ringbuffer.c */, + 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */, + 4BF1364C0F4B0F7700218A3F /* JackResampler.h */, + 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */, + 4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */, + 4B1A93870F49B0E300D3626B /* JackMachTime.c */, + 4B1A93540F49ACFC00D3626B /* JackMachThread.h */, + 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */, + 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */, + 4B1A93520F49ACF300D3626B /* JackNetUnixSocket.h */, + 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */, + 4B1A933C0F49AC4500D3626B /* JackPosixThread.h */, + 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */, + 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */, + 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */, + 4B2791870F72570C000536B7 /* JackGlobals.cpp */, + 32CA4F630368D1EE00C91783 /* iPhoneNet_Prefix.pch */, + 4B0772490F54021B000DC657 /* main_slave.mm */, + 4B0772500F54022D000DC657 /* main_master.mm */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 4B9CB1361136CA99007DE01A /* icon.png */, + 28AD733E0D9D9553002E5188 /* MainWindow.xib */, + 8D1107310486CEB800E47090 /* Info.plist */, + 4BC9C1D31135AA1800D22670 /* iPhoneNetMasterAppl-Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */, + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765FC0DF74451002DB57D /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4B1A940C0F49BDE000D3626B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B1A94140F49BE2C00D3626B /* iPhoneNet_Prefix.pch in Headers */, + 4B1A94160F49BE3000D3626B /* JackMachThread.h in Headers */, + 4B1A941C0F49BE3500D3626B /* JackNetUnixSocket.h in Headers */, + 4B1A941E0F49BE3600D3626B /* JackPosixThread.h in Headers */, + 4BF136130F4B0B5E00218A3F /* JackAudioAdapterInterface.h in Headers */, + 4BF1364F0F4B0F7700218A3F /* JackResampler.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* iPhoneNetSlave */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "iPhoneNetSlave" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iPhoneNetSlave; + productName = iPhoneNet; + productReference = 1D6058910D05DD3D006BFB54 /* NetJackSlave.app */; + productType = "com.apple.product-type.application"; + }; + 4B07721F0F54018C000DC657 /* iPhoneNetMaster */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B0772350F54018C000DC657 /* Build configuration list for PBXNativeTarget "iPhoneNetMaster" */; + buildPhases = ( + 4B0772200F54018C000DC657 /* Resources */, + 4B0772220F54018C000DC657 /* Sources */, + 4B0772300F54018C000DC657 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iPhoneNetMaster; + productName = iPhoneNet; + productReference = 4B0772380F54018C000DC657 /* NetJackMaster.app */; + productType = "com.apple.product-type.application"; + }; + 4B1A940F0F49BDE000D3626B /* libjacknet */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "libjacknet" */; + buildPhases = ( + 4B1A940C0F49BDE000D3626B /* Headers */, + 4B1A940D0F49BDE000D3626B /* Sources */, + 4B1A940E0F49BDE000D3626B /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libjacknet; + productName = jacknet; + productReference = 4BFF45120F4D59DB00106083 /* libjacknet.a */; + productType = "com.apple.product-type.library.static"; + }; + 4B41469610BD3C4300C12F0C /* iPhoneFaustNet Distribution */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B4146AD10BD3C4300C12F0C /* Build configuration list for PBXNativeTarget "iPhoneFaustNet Distribution" */; + buildPhases = ( + 4B41469710BD3C4300C12F0C /* Resources */, + 4B41469910BD3C4300C12F0C /* Sources */, + 4B4146A810BD3C4300C12F0C /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "iPhoneFaustNet Distribution"; + productName = iPhoneNet; + productReference = 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */; + productType = "com.apple.product-type.application"; + }; + 4BCB37B4112D647C008C7BC1 /* iPhoneFaust */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4BCB37CB112D647C008C7BC1 /* Build configuration list for PBXNativeTarget "iPhoneFaust" */; + buildPhases = ( + 4BCB37B5112D647C008C7BC1 /* Resources */, + 4BCB37B7112D647C008C7BC1 /* Sources */, + 4BCB37C6112D647C008C7BC1 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iPhoneFaust; + productName = iPhoneNet; + productReference = 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */; + productType = "com.apple.product-type.application"; + }; + 4BCF75D810BC2FD90082C526 /* iPhoneThruNet */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4BCF75EF10BC2FD90082C526 /* Build configuration list for PBXNativeTarget "iPhoneThruNet" */; + buildPhases = ( + 4BCF75D910BC2FD90082C526 /* Resources */, + 4BCF75DB10BC2FD90082C526 /* Sources */, + 4BCF75EA10BC2FD90082C526 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iPhoneThruNet; + productName = iPhoneNet; + productReference = 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */; + productType = "com.apple.product-type.application"; + }; + 4BDFCD3B113DB6B700D77992 /* iPhoneNetSlaveLib */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4BDFCD54113DB6B700D77992 /* Build configuration list for PBXNativeTarget "iPhoneNetSlaveLib" */; + buildPhases = ( + 4BDFCD3C113DB6B700D77992 /* Resources */, + 4BDFCD3F113DB6B700D77992 /* Sources */, + 4BDFCD4F113DB6B700D77992 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iPhoneNetSlaveLib; + productName = iPhoneNet; + productReference = 4BDFCD57113DB6B700D77992 /* NetJackSlave.app */; + productType = "com.apple.product-type.application"; + }; + 4BFF455E0F4D5D9700106083 /* iPhoneFaustNet */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4BFF45740F4D5D9700106083 /* Build configuration list for PBXNativeTarget "iPhoneFaustNet" */; + buildPhases = ( + 4BFF455F0F4D5D9700106083 /* Resources */, + 4BFF45610F4D5D9700106083 /* Sources */, + 4BFF456F0F4D5D9700106083 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iPhoneFaustNet; + productName = iPhoneNet; + productReference = 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "iPhoneNet" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4B07721F0F54018C000DC657 /* iPhoneNetMaster */, + 1D6058900D05DD3D006BFB54 /* iPhoneNetSlave */, + 4BDFCD3B113DB6B700D77992 /* iPhoneNetSlaveLib */, + 4BFF455E0F4D5D9700106083 /* iPhoneFaustNet */, + 4BCF75D810BC2FD90082C526 /* iPhoneThruNet */, + 4B41469610BD3C4300C12F0C /* iPhoneFaustNet Distribution */, + 4BCB37B4112D647C008C7BC1 /* iPhoneFaust */, + 4B1A940F0F49BDE000D3626B /* libjacknet */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, + 4B9CB1381136CA99007DE01A /* icon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B0772200F54018C000DC657 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B0772210F54018C000DC657 /* MainWindow.xib in Resources */, + 4B9CB1371136CA99007DE01A /* icon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B41469710BD3C4300C12F0C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B41469810BD3C4300C12F0C /* MainWindow.xib in Resources */, + 4B9CB13B1136CA99007DE01A /* icon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BCB37B5112D647C008C7BC1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BCB37B6112D647C008C7BC1 /* MainWindow.xib in Resources */, + 4B9CB13C1136CA99007DE01A /* icon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BCF75D910BC2FD90082C526 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BCF75DA10BC2FD90082C526 /* MainWindow.xib in Resources */, + 4B9CB13A1136CA99007DE01A /* icon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BDFCD3C113DB6B700D77992 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BDFCD3D113DB6B700D77992 /* MainWindow.xib in Resources */, + 4BDFCD3E113DB6B700D77992 /* icon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BFF455F0F4D5D9700106083 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BFF45600F4D5D9700106083 /* MainWindow.xib in Resources */, + 4B9CB1391136CA99007DE01A /* icon.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B1A94540F49C03300D3626B /* JackMachThread.cpp in Sources */, + 4B1A94550F49C03300D3626B /* JackMachTime.c in Sources */, + 4B1A94560F49C03400D3626B /* JackNetAPI.cpp in Sources */, + 4B1A94570F49C03500D3626B /* JackNetInterface.cpp in Sources */, + 4B1A94580F49C03600D3626B /* JackNetTool.cpp in Sources */, + 4B1A94590F49C03600D3626B /* JackNetUnixSocket.cpp in Sources */, + 4B1A945A0F49C03600D3626B /* JackPosixThread.cpp in Sources */, + 4BF1360F0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */, + 4BF1364D0F4B0F7700218A3F /* JackResampler.cpp in Sources */, + 4BF136550F4B0F9F00218A3F /* ringbuffer.c in Sources */, + 4B07724A0F54021B000DC657 /* main_slave.mm in Sources */, + 4B0773870F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, + 4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */, + 4BF15E2611356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, + 4BF15F7911357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B0772220F54018C000DC657 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B0772240F54018C000DC657 /* JackMachThread.cpp in Sources */, + 4B0772250F54018C000DC657 /* JackMachTime.c in Sources */, + 4B0772260F54018C000DC657 /* JackNetAPI.cpp in Sources */, + 4B0772270F54018C000DC657 /* JackNetInterface.cpp in Sources */, + 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */, + 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */, + 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */, + 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */, + 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */, + 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */, + 4B0773860F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, + 4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */, + 4BF15E2511356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, + 4BF15F7811357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, + 4BC9C1F71135AB2800D22670 /* main_master.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B1A940D0F49BDE000D3626B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B1A94150F49BE2F00D3626B /* JackMachThread.cpp in Sources */, + 4B1A94170F49BE3100D3626B /* JackMachTime.c in Sources */, + 4B1A94180F49BE3100D3626B /* JackNetAPI.cpp in Sources */, + 4B1A94190F49BE3300D3626B /* JackNetInterface.cpp in Sources */, + 4B1A941A0F49BE3300D3626B /* JackNetTool.cpp in Sources */, + 4B1A941B0F49BE3400D3626B /* JackNetUnixSocket.cpp in Sources */, + 4B1A941D0F49BE3500D3626B /* JackPosixThread.cpp in Sources */, + 4BF136100F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */, + 4BF1364E0F4B0F7700218A3F /* JackResampler.cpp in Sources */, + 4BF136560F4B0F9F00218A3F /* ringbuffer.c in Sources */, + 4B2791890F72570C000536B7 /* JackGlobals.cpp in Sources */, + 4B6B712C114BAE9A00ED9788 /* CAHostTimeBase.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B41469910BD3C4300C12F0C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B41469A10BD3C4300C12F0C /* JackMachThread.cpp in Sources */, + 4B41469B10BD3C4300C12F0C /* JackMachTime.c in Sources */, + 4B41469C10BD3C4300C12F0C /* JackNetAPI.cpp in Sources */, + 4B41469D10BD3C4300C12F0C /* JackNetInterface.cpp in Sources */, + 4B41469E10BD3C4300C12F0C /* JackNetTool.cpp in Sources */, + 4B41469F10BD3C4300C12F0C /* JackNetUnixSocket.cpp in Sources */, + 4B4146A010BD3C4300C12F0C /* JackPosixThread.cpp in Sources */, + 4B4146A210BD3C4300C12F0C /* JackAudioAdapterInterface.cpp in Sources */, + 4B4146A310BD3C4300C12F0C /* JackResampler.cpp in Sources */, + 4B4146A410BD3C4300C12F0C /* ringbuffer.c in Sources */, + 4B4146A510BD3C4300C12F0C /* iPhoneNetAppDelegate.m in Sources */, + 4B4146A610BD3C4300C12F0C /* freeverb.mm in Sources */, + 4B4146A710BD3C4300C12F0C /* JackGlobals.cpp in Sources */, + 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, + 4BF15F7C11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BCB37B7112D647C008C7BC1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BCB37D9112D64D8008C7BC1 /* iphone-faust.mm in Sources */, + 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, + 4BF15F7D11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BCF75DB10BC2FD90082C526 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BCF75DC10BC2FD90082C526 /* JackMachThread.cpp in Sources */, + 4BCF75DD10BC2FD90082C526 /* JackMachTime.c in Sources */, + 4BCF75DE10BC2FD90082C526 /* JackNetAPI.cpp in Sources */, + 4BCF75DF10BC2FD90082C526 /* JackNetInterface.cpp in Sources */, + 4BCF75E010BC2FD90082C526 /* JackNetTool.cpp in Sources */, + 4BCF75E110BC2FD90082C526 /* JackNetUnixSocket.cpp in Sources */, + 4BCF75E210BC2FD90082C526 /* JackPosixThread.cpp in Sources */, + 4BCF75E410BC2FD90082C526 /* JackAudioAdapterInterface.cpp in Sources */, + 4BCF75E510BC2FD90082C526 /* JackResampler.cpp in Sources */, + 4BCF75E610BC2FD90082C526 /* ringbuffer.c in Sources */, + 4BCF75E710BC2FD90082C526 /* iPhoneNetAppDelegate.m in Sources */, + 4BCF75E910BC2FD90082C526 /* JackGlobals.cpp in Sources */, + 4BCF75F710BC30140082C526 /* audio_thru.mm in Sources */, + 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, + 4BF15F7B11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BDFCD3F113DB6B700D77992 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BDFCD4A113DB6B700D77992 /* main_slave.mm in Sources */, + 4BDFCD4B113DB6B700D77992 /* iPhoneNetAppDelegate.m in Sources */, + 4BDFCD4D113DB6B700D77992 /* CAHostTimeBase.cpp in Sources */, + 4BDFCD4E113DB6B700D77992 /* TiPhoneCoreAudioRenderer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BFF45610F4D5D9700106083 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BFF45630F4D5D9700106083 /* JackMachThread.cpp in Sources */, + 4BFF45640F4D5D9700106083 /* JackMachTime.c in Sources */, + 4BFF45650F4D5D9700106083 /* JackNetAPI.cpp in Sources */, + 4BFF45660F4D5D9700106083 /* JackNetInterface.cpp in Sources */, + 4BFF45670F4D5D9700106083 /* JackNetTool.cpp in Sources */, + 4BFF45680F4D5D9700106083 /* JackNetUnixSocket.cpp in Sources */, + 4BFF45690F4D5D9700106083 /* JackPosixThread.cpp in Sources */, + 4BFF456B0F4D5D9700106083 /* JackAudioAdapterInterface.cpp in Sources */, + 4BFF456C0F4D5D9700106083 /* JackResampler.cpp in Sources */, + 4BFF456D0F4D5D9700106083 /* ringbuffer.c in Sources */, + 4B0773880F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, + 4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */, + 4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */, + 4BF15E2711356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, + 4BF15F7A11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + /usr/local/include, + ../../macosx/coreaudio, + ../../macosx, + ../../posix, + ../../common/jack, + ../../common, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/build/Debug-iphonesimulator\"", + ); + OTHER_LDFLAGS = libcelt.a; + PRODUCT_NAME = NetJackSlave; + SDKROOT = iphoneos3.1.3; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + GCC_THUMB_SUPPORT = NO; + HEADER_SEARCH_PATHS = ( + ., + /usr/local/include, + ../../macosx/coreaudio, + ../../common/jack, + ../../common, + ../../posix, + ../../macosx, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/build/Debug-iphonesimulator\"", + ); + OTHER_LDFLAGS = libcelt.a; + PRODUCT_NAME = NetJackSlave; + SDKROOT = iphoneos3.1.3; + }; + name = Release; + }; + 4B0772360F54018C000DC657 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + /usr/local/include, + ../../macosx/coreaudio, + ../../macosx, + ../../posix, + ../../common/jack, + ../../common, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"", + ); + OTHER_LDFLAGS = libcelt.a; + PRODUCT_NAME = NetJackMaster; + SDKROOT = iphoneos3.1.3; + }; + name = Debug; + }; + 4B0772370F54018C000DC657 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + /usr/local/include, + ../../macosx/coreaudio, + ../../common/jack, + ../../common, + ../../posix, + ../../macosx, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"", + ); + OTHER_LDFLAGS = libcelt.a; + PRODUCT_NAME = NetJackMaster; + }; + name = Release; + }; + 4B1A94110F49BDE100D3626B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + /usr/local/include, + ../../common/jack, + ../../common, + ../../posix, + ../../macosx, + ); + MACH_O_TYPE = staticlib; + PREBINDING = NO; + PRODUCT_NAME = jacknet; + SDKROOT = iphoneos3.1.3; + STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = static; + }; + name = Debug; + }; + 4B1A94120F49BDE100D3626B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + /usr/local/include, + ../../macosx, + ../../posix, + ../../common, + ../../common/jack, + ); + PREBINDING = NO; + PRODUCT_NAME = jacknet; + SDKROOT = iphoneos3.1.3; + ZERO_LINK = NO; + }; + name = Release; + }; + 4B4146AE10BD3C4300C12F0C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Stéphane Letz (8LJEY2RN3N)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../posix, + ../../common/jack, + ../../common, + ); + INFOPLIST_FILE = "Info copy 2.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"", + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = iPhoneFaustNet; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "CEF78041-8E2A-499D-BF7C-8A1B22B6C2AC"; + SDKROOT = iphoneos2.2.1; + }; + name = Debug; + }; + 4B4146AF10BD3C4300C12F0C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../common/jack, + ../../common, + ../../posix, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"", + ); + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = iPhoneFaustNet; + SDKROOT = iphoneos3.1.2; + }; + name = Release; + }; + 4BCB37CC112D647C008C7BC1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + GCC_THUMB_SUPPORT = NO; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../posix, + ../../common/jack, + ../../common, + ); + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 3.1.3; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"", + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = iPhoneFaust; + SDKROOT = iphoneos3.1.3; + }; + name = Debug; + }; + 4BCB37CD112D647C008C7BC1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + GCC_THUMB_SUPPORT = NO; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../common/jack, + ../../common, + ../../posix, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"", + ); + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = iPhoneFaust; + SDKROOT = iphoneos3.1.3; + }; + name = Release; + }; + 4BCF75F010BC2FD90082C526 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../posix, + ../../common/jack, + ../../common, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"", + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = iPhoneThruNet; + SDKROOT = iphoneos2.2.1; + }; + name = Debug; + }; + 4BCF75F110BC2FD90082C526 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + GCC_VERSION = ""; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../common/jack, + ../../common, + ../../posix, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"", + ); + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = iPhoneFaustNet; + }; + name = Release; + }; + 4BDFCD55113DB6B700D77992 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + ../../macosx/coreaudio, + ../../macosx, + ../../posix, + ../../common/jack, + ../../common, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"", + ); + OTHER_LDFLAGS = "-ljacknet"; + PRODUCT_NAME = NetJackSlave; + SDKROOT = iphoneos3.1.3; + }; + name = Debug; + }; + 4BDFCD56113DB6B700D77992 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + ../../macosx/coreaudio, + ../../common/jack, + ../../common, + ../../posix, + ../../macosx, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"", + ); + OTHER_LDFLAGS = "-ljacknet"; + PRODUCT_NAME = NetJackSlave; + }; + name = Release; + }; + 4BFF45750F4D5D9700106083 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../posix, + ../../common/jack, + ../../common, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"", + ); + OTHER_LDFLAGS = ""; + PRODUCT_NAME = iPhoneFaustNet; + SDKROOT = iphoneos2.2.1; + }; + name = Debug; + }; + 4BFF45760F4D5D9700106083 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; + HEADER_SEARCH_PATHS = ( + ../../macosx, + ../../common/jack, + ../../common, + ../../posix, + ); + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"", + ); + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = iPhoneFaustNet; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = iphoneos2.2.1; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = iphoneos2.2.1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "iPhoneNetSlave" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4B0772350F54018C000DC657 /* Build configuration list for PBXNativeTarget "iPhoneNetMaster" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B0772360F54018C000DC657 /* Debug */, + 4B0772370F54018C000DC657 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "libjacknet" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B1A94110F49BDE100D3626B /* Debug */, + 4B1A94120F49BDE100D3626B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4B4146AD10BD3C4300C12F0C /* Build configuration list for PBXNativeTarget "iPhoneFaustNet Distribution" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B4146AE10BD3C4300C12F0C /* Debug */, + 4B4146AF10BD3C4300C12F0C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4BCB37CB112D647C008C7BC1 /* Build configuration list for PBXNativeTarget "iPhoneFaust" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4BCB37CC112D647C008C7BC1 /* Debug */, + 4BCB37CD112D647C008C7BC1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4BCF75EF10BC2FD90082C526 /* Build configuration list for PBXNativeTarget "iPhoneThruNet" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4BCF75F010BC2FD90082C526 /* Debug */, + 4BCF75F110BC2FD90082C526 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4BDFCD54113DB6B700D77992 /* Build configuration list for PBXNativeTarget "iPhoneNetSlaveLib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4BDFCD55113DB6B700D77992 /* Debug */, + 4BDFCD56113DB6B700D77992 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4BFF45740F4D5D9700106083 /* Build configuration list for PBXNativeTarget "iPhoneFaustNet" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4BFF45750F4D5D9700106083 /* Debug */, + 4BFF45760F4D5D9700106083 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "iPhoneNet" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/macosx/iphone/iPhoneNetAppDelegate.h b/macosx/iphone/iPhoneNetAppDelegate.h new file mode 100644 index 00000000..9fcda5bb --- /dev/null +++ b/macosx/iphone/iPhoneNetAppDelegate.h @@ -0,0 +1,23 @@ +// +// iPhoneNetAppDelegate.h +// iPhoneNet +// +// Created by Stéphane LETZ on 16/02/09. +// Copyright Grame 2009. All rights reserved. +// + +#import + +@interface iPhoneNetAppDelegate : NSObject { + // UIWindow *window; + + IBOutlet UIWindow *window; + IBOutlet UINavigationController *navigationController; +} + +//@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) UIWindow *window; +@property (nonatomic, retain) UINavigationController *navigationController; + +@end + diff --git a/macosx/iphone/iPhoneNetAppDelegate.m b/macosx/iphone/iPhoneNetAppDelegate.m new file mode 100644 index 00000000..e867730d --- /dev/null +++ b/macosx/iphone/iPhoneNetAppDelegate.m @@ -0,0 +1,32 @@ +// +// iPhoneNetAppDelegate.m +// iPhoneNet +// +// Created by Stéphane LETZ on 16/02/09. +// Copyright Grame 2009. All rights reserved. +// + +#import "iPhoneNetAppDelegate.h" + +@implementation iPhoneNetAppDelegate + +@synthesize window, navigationController; + + +- (void)applicationDidFinishLaunching:(UIApplication *)application { + + // Override point for customization after application launch + // add the navigation controller's view to the window + [window addSubview: navigationController.view]; + [window makeKeyAndVisible]; +} + + +- (void)dealloc { + [navigationController release]; + [window release]; + [super dealloc]; +} + + +@end diff --git a/macosx/iphone/iPhoneNet_Prefix.pch b/macosx/iphone/iPhoneNet_Prefix.pch new file mode 100644 index 00000000..55c63732 --- /dev/null +++ b/macosx/iphone/iPhoneNet_Prefix.pch @@ -0,0 +1,10 @@ +// +// Prefix header for all source files of the 'iPhoneNet' target in the 'iPhoneNet' project +// + +#ifdef __OBJC__ + #import + #import +#endif + +#define MY_TARGET_OS_IPHONE 1 diff --git a/macosx/iphone/icon.png b/macosx/iphone/icon.png new file mode 100644 index 00000000..9e312ea6 Binary files /dev/null and b/macosx/iphone/icon.png differ diff --git a/macosx/iphone/main_master.mm b/macosx/iphone/main_master.mm new file mode 100644 index 00000000..7ec618b3 --- /dev/null +++ b/macosx/iphone/main_master.mm @@ -0,0 +1,155 @@ +// +// main.m +// iPhoneNet +// +// Created by Stéphane LETZ on 16/02/09. +// Copyright Grame 2009. All rights reserved. +// + +#import +#include + +#include "TiPhoneCoreAudioRenderer.h" + +#define NUM_INPUT 2 +#define NUM_OUTPUT 2 + +jack_net_master_t* net; +jack_adapter_t* adapter; + +float** audio_input_buffer = NULL; +float** audio_output_buffer = NULL; + +int buffer_size = 1024; +int sample_rate = 22050; +//int sample_rate = 32000; + +jack_master_t request = { buffer_size, sample_rate, "master" }; +jack_slave_t result; + +static void MixAudio(float** dst, float** src1, float** src2, int channels, int buffer_size) +{ + for (int chan = 0; chan < channels; chan++) { + for (int frame = 0; frame < buffer_size; frame++) { + dst[chan][frame] = src1[chan][frame] + src2[chan][frame]; + } + } +} + +static void MasterAudioCallback(int frames, float** inputs, float** outputs, void* arg) +{ + int i; + + // Copy from iPod input to network buffers + for (i = 0; i < result.audio_input; i++) { + memcpy(audio_input_buffer[i], inputs[i], buffer_size * sizeof(float)); + } + + /* + // Copy from network out buffers to network in buffers (audio thru) + for (i = 0; i < result.audio_input; i++) { + memcpy(audio_input_buffer[i], audio_output_buffer[i], buffer_size * sizeof(float)); + } + */ + + // Mix iPod input and network in buffers to network out buffers + //MixAudio(audio_input_buffer, inputs, audio_output_buffer, result.audio_input, buffer_size); + + // Send network buffers + if (jack_net_master_send(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) { + printf("jack_net_master_send error..\n"); + } + + // Recv network buffers + if (jack_net_master_recv(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { + printf("jack_net_master_recv error..\n"); + } + + // Copy from network buffers to iPod output + for (i = 0; i < result.audio_output; i++) { + memcpy(outputs[i], audio_output_buffer[i], buffer_size * sizeof(float)); + } +} + +int main(int argc, char *argv[]) { + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int i; + + if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { + printf("jack_net_master_open error..\n"); + return -1; + } + + TiPhoneCoreAudioRenderer audio_device(result.audio_input, result.audio_output); + + // Allocate buffers + if (result.audio_input > 0) { + audio_input_buffer = (float**)calloc(result.audio_input, sizeof(float*)); + for (i = 0; i < result.audio_input; i++) { + audio_input_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); + } + } + + if (result.audio_output > 0) { + audio_output_buffer = (float**)calloc(result.audio_output, sizeof(float*)); + for (i = 0; i < result.audio_output; i++) { + audio_output_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); + } + } + + if (audio_device.Open(buffer_size, sample_rate) < 0) { + return -1; + } + + audio_device.SetAudioCallback(MasterAudioCallback, NULL); + + if (audio_device.Start() < 0) { + return -1; + } + + /* + // Quite brutal way, the application actually does not start completely, the netjack audio processing loop is used instead... + // Run until interrupted + + int wait_usec = (unsigned long)((((float)buffer_size) / ((float)sample_rate)) * 1000000.0f); + + while (1) { + + // Copy input to output + for (i = 0; i < result.audio_input; i++) { + memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); + } + + if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { + printf("jack_net_master_send error..\n"); + } + + if (jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) { + printf("jack_net_master_recv error..\n"); + } + usleep(wait_usec); + }; + */ + + int retVal = UIApplicationMain(argc, argv, nil, nil); + + audio_device.Stop(); + audio_device.Close(); + + // Wait for application end + jack_net_master_close(net); + + for (i = 0; i < result.audio_input; i++) { + free(audio_input_buffer[i]); + } + free(audio_input_buffer); + + for (i = 0; i < result.audio_output; i++) { + free(audio_output_buffer[i]); + } + free(audio_output_buffer); + + [pool release]; + return retVal; +} diff --git a/macosx/iphone/main_slave.mm b/macosx/iphone/main_slave.mm new file mode 100644 index 00000000..b4ef278b --- /dev/null +++ b/macosx/iphone/main_slave.mm @@ -0,0 +1,113 @@ +// +// main.m +// iPhoneNet +// +// Created by Stéphane LETZ on 16/02/09. +// Copyright Grame 2009. All rights reserved. +// + +#import +#include + +#include "TiPhoneCoreAudioRenderer.h" + +#define NUM_INPUT 0 +#define NUM_OUTPUT 2 + +jack_net_slave_t* net = NULL; +jack_adapter_t* adapter = NULL; + +int buffer_size; +int sample_rate; + +static int net_process(jack_nframes_t buffer_size, + int audio_input, + float** audio_input_buffer, + int midi_input, + void** midi_input_buffer, + int audio_output, + float** audio_output_buffer, + int midi_output, + void** midi_output_buffer, + void* data) +{ + jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size); + + // Process input, produce output + if (audio_input == audio_output) { + // Copy net input to net output + for (int i = 0; i < audio_input; i++) { + memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); + } + } + return 0; +} + +static void net_shutdown(void *arg) +{ + if (adapter) + jack_flush_adapter(adapter); +} + +static void SlaveAudioCallback(int frames, float** inputs, float** outputs, void* arg) +{ + jack_adapter_push_and_pull(adapter, inputs, outputs, frames); +} + +//http://www.securityfocus.com/infocus/1884 + +#define WIFI_MTU 1500 + +int main(int argc, char *argv[]) { + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + jack_slave_t request = { NUM_OUTPUT, NUM_INPUT, 0, 0, WIFI_MTU, -1, JackCeltEncoder, 128, JackSlowMode }; + jack_master_t result; + + //if ((net = jack_net_slave_open("169.254.112.119", DEFAULT_PORT, "iPhone", &request, &result)) == 0) { + if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPod", &request, &result)) == 0) { + printf("jack_net_slave_open error..\n"); + return -1; + } + + if ((adapter = jack_create_adapter(NUM_INPUT, + NUM_OUTPUT, + result.buffer_size, + result.sample_rate, + result.buffer_size, + result.sample_rate)) == 0) { + return -1; + } + + TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT); + + jack_set_net_slave_process_callback(net, net_process, NULL); + jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL); + + if (jack_net_slave_activate(net) != 0) { + return -1; + } + + if (audio_device.Open(result.buffer_size, result.sample_rate) < 0) { + return -1; + } + + audio_device.SetAudioCallback(SlaveAudioCallback, NULL); + + if (audio_device.Start() < 0) { + return -1; + } + + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + + audio_device.Stop(); + audio_device.Close(); + + // Wait for application end + jack_net_slave_deactivate(net); + jack_net_slave_close(net); + jack_destroy_adapter(adapter); + return retVal; +} diff --git a/windows/jackd.workspace b/windows/jackd.workspace index d7d8e8d0..98496521 100644 --- a/windows/jackd.workspace +++ b/windows/jackd.workspace @@ -20,6 +20,7 @@ + diff --git a/windows/libjacknet.cbp b/windows/libjacknet.cbp new file mode 100644 index 00000000..18b88c61 --- /dev/null +++ b/windows/libjacknet.cbp @@ -0,0 +1,149 @@ + + + + + + diff --git a/windows/libjacknet.rc b/windows/libjacknet.rc new file mode 100644 index 00000000..b6e11113 --- /dev/null +++ b/windows/libjacknet.rc @@ -0,0 +1,41 @@ +// Generated by ResEdit 1.4.3 +// Copyright (C) 2006-2008 +// http://www.resedit.net + +#include "resource.h" +#include "afxres.h" + + +// +// Version Information resources +// +LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT +1 VERSIONINFO + FILEVERSION 1,9,3,0 + PRODUCTVERSION 1,9,3,0 + FILEOS VOS_UNKNOWN + FILETYPE VFT_DLL +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040c04b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Grame\0" + VALUE "FileDescription", "Jack Net library for Windows\0" + VALUE "FileVersion", "1, 9, 3, 0\0" + VALUE "InternalName", "libjacknet\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2009\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "libjacknet.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "libjacknet\0" + VALUE "ProductVersion", "1, 9, 3, 0\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 1036, 1200 + END +END