From 217d8d2380fddcc9cc837c7820490115facff96a Mon Sep 17 00:00:00 2001 From: Dennis Braun Date: Wed, 12 Aug 2020 16:40:55 +0200 Subject: [PATCH] New upstream version 1.2.1+ds0 --- .gitignore | 3 + .travis.yml | 42 +++++++++ CHANGESLOG.txt | 6 +- INSTALL.txt | 2 +- INSTALL_meson.md | 23 +++++ JMess.cpp | 4 +- README.md | 2 +- meson.build | 45 +++++++++ src/DataProtocol.h | 9 ++ src/JMess.cpp | 19 ++-- src/JMess.h | 2 + src/JackTrip.cpp | 91 ++++++++++++++----- src/JackTrip.h | 17 ++-- src/JackTripWorker.cpp | 23 +++-- src/JackTripWorker.h | 6 +- src/RingBuffer.cpp | 16 ++++ src/RingBuffer.h | 9 ++ src/Settings.cpp | 44 +++++++-- src/Settings.h | 8 ++ src/UdpDataProtocol.cpp | 61 ++++++++++--- src/UdpDataProtocol.h | 17 +++- ...pMasterListener.cpp => UdpHubListener.cpp} | 60 +++++++----- src/{UdpMasterListener.h => UdpHubListener.h} | 25 +++-- src/build | 13 ++- src/jacktrip.pro | 8 +- src/jacktrip_globals.h | 10 +- 26 files changed, 436 insertions(+), 129 deletions(-) create mode 100644 .travis.yml create mode 100644 INSTALL_meson.md create mode 100644 meson.build rename src/{UdpMasterListener.cpp => UdpHubListener.cpp} (89%) rename src/{UdpMasterListener.h => UdpHubListener.h} (89%) diff --git a/.gitignore b/.gitignore index 1afe92a..c9dcabe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ # QtCreator user files *.pro.user *.pro.user.* + +# build directory +builddir/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f551d99 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,42 @@ +os: + - linux + - osx + +language: + - cpp + +# force updated ubuntu distribution with up-to-date gcc +dist: bionic + +branches: + - master + +env: + global: + - PKGS_OSX="jack qt rt-audio" + +addons: + apt: + update: true + packages: + - qt5-default + - qttools5-dev-tools + - libjack-dev + - librtaudio-dev + +before_script: + # manually install brew packages as addon: homebrew is broken in the default osx image + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install $PKGS_OSX; fi + # mac: workaround for homebrew qmake not being symlinked into $PATH + # see https://stackoverflow.com/questions/48847505/why-cant-i-use-qmake-on-mac-after-installing-it + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then export PATH="/usr/local/opt/qt/bin:$PATH"; fi + +script: + - cd src + - ./build + +after_success: + - echo "Success!" + +after_failure: + - echo "Something went wrong :(" diff --git a/CHANGESLOG.txt b/CHANGESLOG.txt index c8dc135..3377943 100644 --- a/CHANGESLOG.txt +++ b/CHANGESLOG.txt @@ -1,5 +1,9 @@ --- -master +1.2.1 (master) (branch name will be deprecated) +(main and dev) (new branches, respectively for stable and development) +- (added) src/build script builds in ../builddir +- (fixed) refactor "Master" to be "Hub" +- (fixed) 1.2.1 correctly versioned and tagged --- 1.2 (release candidate, not yet tagged) diff --git a/INSTALL.txt b/INSTALL.txt index 2ca1624..f8b23dc 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -103,7 +103,7 @@ $ qmake -config nojack jacktrip.pro $ make release -If you want to install (using Terminal): on the /src directory type: +If you want to install (using Terminal): on the /builddir directory type: $ sudo cp jacktrip /usr/local/bin/ (enter your password when prompted) diff --git a/INSTALL_meson.md b/INSTALL_meson.md new file mode 100644 index 0000000..fda5b39 --- /dev/null +++ b/INSTALL_meson.md @@ -0,0 +1,23 @@ +# Build and Installation Instructions with Meson + +## Install Dependencies + +Fedora: +dnf install meson qt5-qtbase-devel rtaudio-devel jack-audio-connection-kit-devel + +Debian/Ubuntu: +apt install meson build-essential qtbase5-dev librtaudio-dev libjack-jackd2-dev + +MacOS with brew (not tested): +brew install meson qt rt-audio jack + +## Build + +Prepare your build directory (by default debug and nonoptimized): +meson builddir + +Now build with: +ninja -C builddir + +Install with: +ninja -C builddir install diff --git a/JMess.cpp b/JMess.cpp index 30b20dc..2708bc4 100644 --- a/JMess.cpp +++ b/JMess.cpp @@ -167,7 +167,7 @@ void JMess::setConnectedPorts() } //******************************************************************************* void JMess::connectSpawnedPorts(int nChans, int hubPatch) -// called from UdpMasterListener::connectMesh +// called from UdpHubListener::connectMesh { QString IPS[gMAX_WAIRS]; int ctr = 0; @@ -307,7 +307,7 @@ void JMess::connectSpawnedPorts(int nChans, int hubPatch) // this is brute force, does not look at individual clients, just patches the whole ensemble // each time void JMess::connectTUB(int /*nChans*/) -// called from UdpMasterListener::connectPatch +// called from UdpHubListener::connectPatch { for (int i = 0; i<=gMAX_TUB-gMIN_TUB; i++) // last IP decimal octet for (int l = 1; l<=1; l++) // mono for now // chans are 1-based, 1...2 diff --git a/README.md b/README.md index 9490616..201635e 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ And as of spring 2020 it moved back to GitHub for the current development. ## Links ## * Preliminary [Documentation](http://ccrma.stanford.edu/groups/soundwire/software/jacktrip/) and [API](http://ccrma.stanford.edu/groups/soundwire/software/jacktrip/annotated.html). * Subscribe to the [Mailing List](http://groups.google.com/group/jacktrip-users). - * [CCRMA](http://ccrma.stanford.edu/) . + * [CCRMA](http://ccrma.stanford.edu/). * [SoundWIRE group](http://ccrma.stanford.edu/groups/soundwire/). * [Juan-Pablo Caceres](https://ccrma.stanford.edu/~jcaceres/). diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..6debd45 --- /dev/null +++ b/meson.build @@ -0,0 +1,45 @@ +project('jacktrip', 'cpp', version: '1.2') +qt5 = import('qt5') +qt5_dep = dependency('qt5', modules: ['Core', 'Network']) +jack_dep = dependency('jack') +rtaudio_dep = dependency('rtaudio') +thread_dep = dependency('threads') + +defines = [] +if host_machine.system() == 'linux' + defines += '-D__LINUX__' +elif host_machine.system() == 'osx' + defines += '-D__MAC_OSX__' +elif host_machine.system() == 'windows' + defines += '-D__WIN_32__' +endif + +moc_h = ['src/DataProtocol.h', + 'src/JackTrip.h', + 'src/JackTripWorker.h', + 'src/JackTripWorkerMessages.h', + 'src/NetKS.h', + 'src/PacketHeader.h', + 'src/Settings.h', + 'src/UdpDataProtocol.h', + 'src/UdpHubListener.h'] +moc_files = qt5.preprocess(moc_headers : moc_h) + +src = ['src/DataProtocol.cpp', + 'src/JMess.cpp', + 'src/JackTrip.cpp', + 'src/jacktrip_globals.cpp', + 'src/jacktrip_main.cpp', + 'src/JackTripThread.cpp', + 'src/JackTripWorker.cpp', + 'src/LoopBack.cpp', + 'src/PacketHeader.cpp', + 'src/ProcessPlugin.cpp', + 'src/RingBuffer.cpp', + 'src/Settings.cpp', + 'src/UdpDataProtocol.cpp', + 'src/UdpHubListener.cpp', + 'src/AudioInterface.cpp', + 'src/JackAudioInterface.cpp'] + +executable('jacktrip', src, moc_files, dependencies: [qt5_dep, jack_dep, rtaudio_dep, thread_dep], cpp_args: defines, install: true ) diff --git a/src/DataProtocol.h b/src/DataProtocol.h index 816e6a8..413263d 100644 --- a/src/DataProtocol.h +++ b/src/DataProtocol.h @@ -171,6 +171,15 @@ public: virtual void setSocket(int &socket) = 0; #endif + struct PktStat { + uint32_t tot; + uint32_t lost; + uint32_t outOfOrder; + uint32_t revived; + uint32_t statCount; + }; + virtual bool getStats(PktStat*) {return false;} + signals: void signalError(const char* error_message); diff --git a/src/JMess.cpp b/src/JMess.cpp index b49008c..8cdab74 100644 --- a/src/JMess.cpp +++ b/src/JMess.cpp @@ -35,6 +35,8 @@ #include "jacktrip_globals.h" #include +// sJackMutex definition +QMutex JMess::sJMessMutex; //------------------------------------------------------------------------------- /*! \brief Constructs a JMess object that has a jack client. @@ -167,8 +169,11 @@ void JMess::setConnectedPorts() } //******************************************************************************* void JMess::connectSpawnedPorts(int nChans, int hubPatch) -// called from UdpMasterListener::connectMesh +// called from UdpHubListener::connectMesh { + + QMutexLocker locker(&sJMessMutex); + QString IPS[gMAX_WAIRS]; int ctr = 0; @@ -197,7 +202,7 @@ void JMess::connectSpawnedPorts(int nChans, int hubPatch) // qDebug() << ports[out_i] << systemPort << s; } } - for (int i = 0; i //#include //#include +#include #include @@ -87,5 +88,6 @@ private: //OuputPortN InputPortN QVector > mConnectedPorts; QVector > mPortsToConnect; + static QMutex sJMessMutex; ///< Mutex to make thread safe jack functions that are not }; #endif diff --git a/src/JackTrip.cpp b/src/JackTrip.cpp index 85d91cd..c425851 100644 --- a/src/JackTrip.cpp +++ b/src/JackTrip.cpp @@ -52,6 +52,8 @@ #include #include #include +#include +#include using std::cout; using std::endl; @@ -104,12 +106,13 @@ JackTrip::JackTrip(jacktripModeT JacktripMode, mReceiverPeerPort(receiver_peer_port), mTcpServerPort(4464), mRedundancy(redundancy), - mJackClientName("JackTrip"), + mJackClientName(gJackDefaultClientName), mConnectionMode(JackTrip::NORMAL), mReceivedConnection(false), mTcpConnectionError(false), mStopped(false), - mConnectDefaultAudioPorts(true) + mConnectDefaultAudioPorts(true), + mIOStatLogStream(std::cout.rdbuf()) { createHeader(mPacketHeaderType); } @@ -130,7 +133,7 @@ JackTrip::~JackTrip() //******************************************************************************* void JackTrip::setupAudio( - #ifdef WAIRTOMASTER // WAIR + #ifdef WAIRTOHUB // WAIR int ID #endif // endwhere ) @@ -153,15 +156,14 @@ void JackTrip::setupAudio( #endif // endwhere mAudioBitResolution); -#ifdef WAIRTOMASTER // WAIR - qDebug() << "mPeerAddress" << mPeerAddress << mPeerAddress.contains(gDOMAIN_TRIPLE); - QString VARIABLE_AUDIO_NAME = WAIR_AUDIO_NAME; // legacy for WAIR - QByteArray tmp = QString(mPeerAddress).replace(":", ".").toLatin1(); - if(mPeerAddress.toStdString()!="") - mJackClientName = tmp.constData(); - std::cout << "WAIR ID " << ID << " jacktrip client name set to=" << - mJackClientName << std::endl; - +#ifdef WAIRTOHUB // WAIR + //Set our Jack client name if we're a hub server or a custom name hasn't been set + if ( mPeerAddress.toStdString() != "" && + (mJackClientName == gJackDefaultClientName || mJackTripMode == SERVERPINGSERVER)) { + mJackClientName = QString(mPeerAddress).replace(":", ".").toLatin1().constData(); + } +// std::cout << "WAIR ID " << ID << " jacktrip client name set to=" << +// mJackClientName << std::endl; #endif // endwhere mAudioInterface->setClientName(mJackClientName); @@ -316,10 +318,10 @@ void JackTrip::appendProcessPlugin(ProcessPlugin* plugin) //******************************************************************************* void JackTrip::startProcess( - #ifdef WAIRTOMASTER // WAIR + #ifdef WAIRTOHUB // WAIR int ID #endif // endwhere - ) throw(std::invalid_argument) + ) { //signal that catches ctrl c in rtaudio-asio mode #if defined (__WIN_32__) if (signal(SIGINT, sigint_handler) == SIG_ERR) { @@ -333,10 +335,8 @@ void JackTrip::startProcess( if (gVerboseFlag) std::cout << " JackTrip:startProcess before checkIfPortIsBinded(mReceiverBindPort)" << std::endl; #if defined __WIN_32__ - //cc fixed windows crash with this print statement! - qDebug() << "before mJackTrip->startProcess" - << mReceiverBindPort<< mSenderBindPort; - // msleep(2000); + //cc fixed windows crash with this print statement! hope to delete +// qDebug() << "before mJackTrip->startProcess" << mReceiverBindPort<< mSenderBindPort; #endif checkIfPortIsBinded(mReceiverBindPort); if (gVerboseFlag) std::cout << " JackTrip:startProcess before checkIfPortIsBinded(mSenderBindPort)" << std::endl; @@ -345,7 +345,7 @@ void JackTrip::startProcess( // ------------------------------ if (gVerboseFlag) std::cout << " JackTrip:startProcess before setupAudio" << std::endl; setupAudio( - #ifdef WAIRTOMASTER // wair + #ifdef WAIRTOHUB // wair ID #endif // endwhere ); @@ -437,6 +437,54 @@ void JackTrip::startProcess( if (mConnectDefaultAudioPorts) { mAudioInterface->connectDefaultPorts(); } } +//******************************************************************************* +void JackTrip::startIOStatTimer(int timeout_sec, const std::ostream& log_stream) +{ + mIOStatLogStream.rdbuf(log_stream.rdbuf()); + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(onStatTimer())); + timer->start(timeout_sec*1000); +} + +//******************************************************************************* +void JackTrip::onStatTimer() +{ + DataProtocol::PktStat pkt_stat; + if (!mDataProtocolReceiver->getStats(&pkt_stat)) { + return; + } + bool reset = (0 == pkt_stat.statCount); + RingBuffer::IOStat recv_io_stat; + if (!mReceiveRingBuffer->getStats(&recv_io_stat, reset)) { + return; + } + RingBuffer::IOStat send_io_stat; + if (!mSendRingBuffer->getStats(&send_io_stat, reset)) { + return; + } + QString now = QDateTime::currentDateTime().toString(Qt::ISODate); + int32_t skew = recv_io_stat.underruns - recv_io_stat.overflows + - pkt_stat.lost + pkt_stat.revived; + + static QMutex mutex; + QMutexLocker locker(&mutex); + mIOStatLogStream << now.toLocal8Bit().constData() + << " " << getPeerAddress().toLocal8Bit().constData() + << " send: " + << send_io_stat.underruns + << "/" << send_io_stat.overflows + << " recv: " + << recv_io_stat.underruns + << "/" << recv_io_stat.overflows + << " prot: " + << pkt_stat.lost + << "/" << pkt_stat.outOfOrder + << "/" << pkt_stat.revived + << " tot: " + << pkt_stat.tot + << " skew: " << skew + << endl; +} //******************************************************************************* void JackTrip::stop() @@ -470,7 +518,7 @@ void JackTrip::waitThreads() //******************************************************************************* -void JackTrip::clientStart() throw(std::invalid_argument) +void JackTrip::clientStart() { // For the Client mode, the peer (or server) address has to be specified by the user if ( mPeerAddress.isEmpty() ) { @@ -487,7 +535,6 @@ void JackTrip::clientStart() throw(std::invalid_argument) //******************************************************************************* int JackTrip::serverStart(bool timeout, int udpTimeout) // udpTimeout unused -throw(std::invalid_argument, std::runtime_error) { // Set the peer address if ( !mPeerAddress.isEmpty() ) { @@ -584,7 +631,7 @@ throw(std::invalid_argument, std::runtime_error) //******************************************************************************* -int JackTrip::clientPingToServerStart() throw(std::invalid_argument) +int JackTrip::clientPingToServerStart() { //mConnectionMode = JackTrip::KSTRONG; //mConnectionMode = JackTrip::JAMTEST; diff --git a/src/JackTrip.h b/src/JackTrip.h index aa00a2c..594e22a 100644 --- a/src/JackTrip.h +++ b/src/JackTrip.h @@ -161,10 +161,10 @@ public: /// \brief Start the processing threads virtual void startProcess( - #ifdef WAIRTOMASTER // wair + #ifdef WAIRTOHUB // wair int ID #endif // endwhere - ) throw(std::invalid_argument); + ); /// \brief Stop the processing threads virtual void stop(); @@ -392,6 +392,8 @@ public: void printTextTest() {std::cout << "=== JackTrip PRINT ===" << std::endl;} void printTextTest2() {std::cout << "=== JackTrip PRINT2 ===" << std::endl;} + void startIOStatTimer(int timeout_sec, const std::ostream& log_stream); + public slots: /// \brief Slot to stop all the processes and threads virtual void slotStopProcesses() @@ -418,6 +420,7 @@ public slots: { std::cout << "=== TESTING ===" << std::endl; } void slotReceivedConnectionFromPeer() { mReceivedConnection = true; } + void onStatTimer(); signals: @@ -434,7 +437,7 @@ public: /// \brief Set the AudioInteface object virtual void setupAudio( - #ifdef WAIRTOMASTER // WAIR + #ifdef WAIRTOHUB // WAIR int ID #endif // endwhere ); @@ -445,16 +448,15 @@ public: /// \brief Set the RingBuffer objects void setupRingBuffers(); /// \brief Starts for the CLIENT mode - void clientStart() throw(std::invalid_argument); + void clientStart(); /// \brief Starts for the SERVER mode /// \param timout Set the server to timeout after 2 seconds if no client connections are received. /// Usefull for the multithreaded server /// \return 0 on success, -1 on error - int serverStart(bool timeout = false, int udpTimeout = gTimeOutMultiThreadedServer) - throw(std::invalid_argument, std::runtime_error); + int serverStart(bool timeout = false, int udpTimeout = gTimeOutMultiThreadedServer); /// \brief Stats for the Client to Ping Server /// \return -1 on error, 0 on success - virtual int clientPingToServerStart() throw(std::invalid_argument); + virtual int clientPingToServerStart(); private: //void bindReceiveSocket(QUdpSocket& UdpSocket, int bind_port, @@ -510,6 +512,7 @@ private: volatile bool mStopped; bool mConnectDefaultAudioPorts; ///< Connect or not default audio ports + std::ostream mIOStatLogStream; }; #endif diff --git a/src/JackTripWorker.cpp b/src/JackTripWorker.cpp index 84b825f..f006261 100644 --- a/src/JackTripWorker.cpp +++ b/src/JackTripWorker.cpp @@ -44,9 +44,10 @@ #include "JackTripWorker.h" #include "JackTrip.h" -#include "UdpMasterListener.h" +#include "UdpHubListener.h" #include "NetKS.h" #include "LoopBack.h" +#include "Settings.h" #ifdef WAIR // wair #include "dcblock2gain.dsp.h" #endif // endwhere @@ -57,8 +58,8 @@ using std::cout; using std::endl; //******************************************************************************* -JackTripWorker::JackTripWorker(UdpMasterListener* udpmasterlistener, int BufferQueueLength, JackTrip::underrunModeT UnderRunMode) : - mUdpMasterListener(udpmasterlistener), +JackTripWorker::JackTripWorker(UdpHubListener* udpmasterlistener, int BufferQueueLength, JackTrip::underrunModeT UnderRunMode) : + mUdpHubListener(udpmasterlistener), m_connectDefaultAudioPorts(false), mBufferQueueLength(BufferQueueLength), mUnderRunMode(UnderRunMode), @@ -79,7 +80,7 @@ JackTripWorker::JackTripWorker(UdpMasterListener* udpmasterlistener, int BufferQ //******************************************************************************* JackTripWorker::~JackTripWorker() { - //delete mUdpMasterListener; + //delete mUdpHubListener; } @@ -127,13 +128,14 @@ void JackTripWorker::run() // Create and setup JackTrip Object //JackTrip jacktrip(JackTrip::SERVER, JackTrip::UDP, mNumChans, 2); if (gVerboseFlag) cout << "---> JackTripWorker: Creating jacktrip objects..." << endl; + Settings* settings = mUdpHubListener->getSettings(); #ifdef WAIR // WAIR // forces BufferQueueLength to 2 // need to parse numNetChans from incoming header // but force to 16 for now #define FORCEBUFFERQ 2 - if (mUdpMasterListener->isWAIR()) { // invoked with -Sw + if (mUdpHubListener->isWAIR()) { // invoked with -Sw mWAIR = true; mNumNetRevChans = NUMNETREVCHANSbecauseNOTINRECEIVEDheader; } else {}; @@ -208,7 +210,7 @@ void JackTripWorker::run() if (gVerboseFlag) cout << "---> JackTripWorker: setJackTripFromClientHeader..." << endl; int PeerConnectionMode = setJackTripFromClientHeader(jacktrip); if ( PeerConnectionMode == -1 ) { - mUdpMasterListener->releaseThread(mID); + mUdpHubListener->releaseThread(mID); { QMutexLocker locker(&mMutex); mSpawning = false; } return; } @@ -216,10 +218,13 @@ void JackTripWorker::run() // Start Threads and event loop if (gVerboseFlag) cout << "---> JackTripWorker: startProcess..." << endl; jacktrip.startProcess( - #ifdef WAIRTOMASTER // wair + #ifdef WAIRTOHUB // wair mID #endif // endwhere ); + if (0 != settings->getIOStatTimeout()) { + jacktrip.startIOStatTimer(settings->getIOStatTimeout(), settings->getIOStatStream()); + } // if (gVerboseFlag) cout << "---> JackTripWorker: start..." << endl; // jacktrip.start(); // ########### JamTest Only ################# @@ -240,14 +245,14 @@ void JackTripWorker::run() std::cerr << "Couldn't send thread to the Pool" << endl; std::cerr << e.what() << endl; std::cerr << gPrintSeparator << endl; - mUdpMasterListener->releaseThread(mID); + mUdpHubListener->releaseThread(mID); { QMutexLocker locker(&mMutex); mSpawning = false; } return; } { QMutexLocker locker(&mMutex); - mUdpMasterListener->releaseThread(mID); + mUdpHubListener->releaseThread(mID); } cout << "JackTrip ID = " << mID << " released from the THREAD POOL" << endl; diff --git a/src/JackTripWorker.h b/src/JackTripWorker.h index 06760e5..62c65da 100644 --- a/src/JackTripWorker.h +++ b/src/JackTripWorker.h @@ -50,7 +50,7 @@ #include "jacktrip_globals.h" //class JackTrip; // forward declaration -class UdpMasterListener; // forward declaration +class UdpHubListener; // forward declaration /** \brief Prototype of the worker class that will be cloned through sending threads to the @@ -70,7 +70,7 @@ class JackTripWorker : public QObject, public QRunnable public: /// \brief The class constructor - JackTripWorker(UdpMasterListener* udpmasterlistener, int BufferQueueLength = gDefaultQueueLength, JackTrip::underrunModeT UnderRunMode = JackTrip::WAVETABLE); + JackTripWorker(UdpHubListener* udpmasterlistener, int BufferQueueLength = gDefaultQueueLength, JackTrip::underrunModeT UnderRunMode = JackTrip::WAVETABLE); /// \brief The class destructor virtual ~JackTripWorker(); @@ -111,7 +111,7 @@ private: int setJackTripFromClientHeader(JackTrip& jacktrip); JackTrip::connectionModeT getConnectionModeFromHeader(); - UdpMasterListener* mUdpMasterListener; ///< Master Listener Socket + UdpHubListener* mUdpHubListener; ///< Hub Listener Socket //QHostAddress mClientAddress; ///< Client Address QString mClientAddress; uint16_t mServerPort; ///< Server Ephemeral Incomming Port to use with Client diff --git a/src/RingBuffer.cpp b/src/RingBuffer.cpp index 5b95161..124399e 100644 --- a/src/RingBuffer.cpp +++ b/src/RingBuffer.cpp @@ -86,6 +86,8 @@ RingBuffer::RingBuffer(int SlotSize, int NumSlots) : mWritePosition = ( (NumSlots/2) * SlotSize ) % mTotalSize; // Udpate Full Slots accordingly mFullSlots = (NumSlots/2); + mUnderruns = 0; + mOverflows = 0; } @@ -226,6 +228,7 @@ void RingBuffer::underrunReset() //mFullSlots += mNumSlots/2; // There's nothing new to read, so we clear the whole buffer (Set the entire buffer to 0) std::memset(mRingBuffer, 0, mTotalSize); + ++mUnderruns; } @@ -237,6 +240,7 @@ void RingBuffer::overflowReset() //mReadPosition = ( mWritePosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize; mReadPosition = ( mReadPosition + ( (mNumSlots/2) * mSlotSize ) ) % mTotalSize; mFullSlots -= mNumSlots/2; + mOverflows += mNumSlots/2 + 1; } @@ -248,3 +252,15 @@ void RingBuffer::debugDump() const cout << "mWritePosition = " << mWritePosition << endl; cout << "mFullSlots = " << mFullSlots << endl; } + +//******************************************************************************* +bool RingBuffer::getStats(RingBuffer::IOStat* stat, bool reset) +{ + if (reset) { + mUnderruns = 0; + mOverflows = 0; + } + stat->underruns = mUnderruns; + stat->overflows = mOverflows; + return true; +} diff --git a/src/RingBuffer.h b/src/RingBuffer.h index 5da8208..78e137f 100644 --- a/src/RingBuffer.h +++ b/src/RingBuffer.h @@ -44,6 +44,8 @@ #include "jacktrip_types.h" +#include + //using namespace JackTripNamespace; @@ -100,6 +102,11 @@ public: */ void readSlotNonBlocking(int8_t* ptrToReadSlot); + struct IOStat { + uint32_t underruns; + uint32_t overflows; + }; + virtual bool getStats(IOStat* stat, bool reset); protected: @@ -139,6 +146,8 @@ private: QMutex mMutex; ///< Mutex to protect read and write operations QWaitCondition mBufferIsNotFull; ///< Buffer not full condition to monitor threads QWaitCondition mBufferIsNotEmpty; ///< Buffer not empty condition to monitor threads + std::atomic mUnderruns; + std::atomic mOverflows; }; #endif diff --git a/src/Settings.cpp b/src/Settings.cpp index 25caf47..541ee8a 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -44,7 +44,7 @@ #include "Stk16.dsp.h" #endif // endwhere -#include "UdpMasterListener.h" +#include "UdpHubListener.h" #include "JackTripWorker.h" #include "jacktrip_globals.h" @@ -85,7 +85,8 @@ Settings::Settings() : mChanfeDefaultID(0), mChanfeDefaultBS(false), mHubConnectionMode(JackTrip::SERVERTOCLIENT), - mConnectDefaultAudioPorts(true) + mConnectDefaultAudioPorts(true), + mIOStatTimeout(0) {} //******************************************************************************* @@ -140,6 +141,8 @@ void Settings::parseInput(int argc, char** argv) { "version", no_argument, NULL, 'v' }, // Version Number { "verbose", no_argument, NULL, 'V' }, // Verbose mode { "hubpatch", required_argument, NULL, 'p' }, // Set hubConnectionMode for auto patch in Jack + { "iostat", required_argument, NULL, 'I' }, // Set IO stat timeout + { "iostatlog", required_argument, NULL, 'G' }, // Set IO stat log file { "help", no_argument, NULL, 'h' }, // Print Help { NULL, 0, NULL, 0 } }; @@ -288,7 +291,7 @@ void Settings::parseInput(int argc, char** argv) case 'v': //------------------------------------------------------- cout << "JackTrip VERSION: " << gVersion << endl; - cout << "Copyright (c) 2008-2018 Juan-Pablo Caceres, Chris Chafe." << endl; + cout << "Copyright (c) 2008-2020 Juan-Pablo Caceres, Chris Chafe." << endl; cout << "SoundWIRE group at CCRMA, Stanford University" << endl; cout << "" << endl; std::exit(0); @@ -316,6 +319,25 @@ void Settings::parseInput(int argc, char** argv) printUsage(); std::exit(1); } break; + case 'I': // IO Stat timeout + //------------------------------------------------------- + mIOStatTimeout = atoi(optarg); + if (0 > mIOStatTimeout) { + std::cerr << "--iostat ERROR: negative timeout." << endl; + printUsage(); + std::exit(1); + } + break; + case 'G': // IO Stat log file + //------------------------------------------------------- + mIOStatStream.open(optarg); + if (!mIOStatStream.is_open()) { + std::cerr << "--iostatlog FAILED to open " << optarg + << " for writing." << endl; + printUsage(); + std::exit(1); + } + break; case 'h': //------------------------------------------------------- printUsage(); @@ -349,7 +371,7 @@ void Settings::printUsage() cout << "" << endl; cout << "JackTrip: A System for High-Quality Audio Network Performance" << endl; cout << "over the Internet" << endl; - cout << "Copyright (c) 2008-2018 Juan-Pablo Caceres, Chris Chafe." << endl; + cout << "Copyright (c) 2008-2020 Juan-Pablo Caceres, Chris Chafe." << endl; cout << "SoundWIRE group at CCRMA, Stanford University" << endl; cout << "VERSION: " << gVersion << endl; cout << "" << endl; @@ -386,7 +408,7 @@ void Settings::printUsage() cout << " -j, --jamlink Run in JamLink Mode (Connect to a JamLink Box)" << endl; cout << " --clientname Change default client name (default: JackTrip)" << endl; cout << " --localaddress Change default local host IP address (default: 127.0.0.1)" << endl; - cout << " --nojackportsconnect Don't connect default audio ports in jack" << endl; + cout << " --nojackportsconnect Don't connect default audio ports in jack, including not doing hub auto audio patch in HUB SERVER mode." << endl; cout << endl; cout << "ARGUMENTS TO USE JACKTRIP WITHOUT JACK:" << endl; cout << " --rtaudio Use system's default sound system instead of Jack" << endl; @@ -394,6 +416,10 @@ void Settings::printUsage() cout << " --bufsize # Set the buffer size, works on --rtaudio mode only (default: 128)" << endl; cout << " --deviceid # The rtaudio device id --rtaudio mode only (default: 0)" << endl; cout << endl; + cout << "ARGUMENTS TO DISPLAY IO STATISTICS:" << endl; + cout << " --iostat Turn on IO stat reporting with specified interval (in seconds)" << endl; + cout << " --iostatlog Save stat log into a file (default: print in stdout)" << endl; + cout << endl; cout << "HELP ARGUMENTS: " << endl; cout << " -v, --version Prints Version Number" << endl; cout << " -V, --verbose Verbose mode, prints debug messages" << endl; @@ -408,7 +434,8 @@ void Settings::startJackTrip() /// \todo Change this, just here to test if ( mJackTripServer ) { - UdpMasterListener* udpmaster = new UdpMasterListener; + UdpHubListener* udpmaster = new UdpHubListener; + udpmaster->setSettings(this); #ifdef WAIR // WAIR udpmaster->setWAIR(mWAIR); #endif // endwhere @@ -569,10 +596,13 @@ void Settings::startJackTrip() // Start JackTrip if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->startProcess" << std::endl; mJackTrip->startProcess( - #ifdef WAIRTOMASTER // WAIR + #ifdef WAIRTOHUB // WAIR 0 // for WAIR compatibility, ID in jack client name #endif // endwhere ); + if (0 < getIOStatTimeout()) { + mJackTrip->startIOStatTimer(getIOStatTimeout(), getIOStatStream()); + } // if (gVerboseFlag) std::cout << "Settings:startJackTrip before mJackTrip->start" << std::endl; // this is a noop // mJackTrip->start(); diff --git a/src/Settings.h b/src/Settings.h index 9272755..dba212e 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -40,6 +40,7 @@ #define __SETTINGS_H__ #include +#include #include "DataProtocol.h" @@ -69,6 +70,11 @@ public: void printUsage(); bool getLoopBack() { return mLoopBack; } + int getIOStatTimeout() const {return mIOStatTimeout;} + const std::ostream& getIOStatStream() const + { + return mIOStatStream.is_open() ? (std::ostream&)mIOStatStream : std::cout; + } public slots: @@ -113,6 +119,8 @@ private: unsigned int mAudioBufferSize; unsigned int mHubConnectionMode; bool mConnectDefaultAudioPorts; ///< Connect or not jack audio ports + int mIOStatTimeout; + std::ofstream mIOStatStream; }; #endif diff --git a/src/UdpDataProtocol.cpp b/src/UdpDataProtocol.cpp index b08ae9e..85738a6 100644 --- a/src/UdpDataProtocol.cpp +++ b/src/UdpDataProtocol.cpp @@ -51,7 +51,7 @@ #include //cc need SD_SEND #include // for IPv6 #endif -#if defined (__LINUX__) || (__MAC__OSX__) +#if defined (__LINUX__) || (__MAC_OSX__) #include // for POSIX Sockets #endif @@ -98,10 +98,10 @@ UdpDataProtocol::~UdpDataProtocol() //******************************************************************************* -void UdpDataProtocol::setPeerAddress(const char* peerHostOrIP) throw(std::invalid_argument) +void UdpDataProtocol::setPeerAddress(const char* peerHostOrIP) { // Get DNS Address -#if defined (__LINUX__) || (__MAC__OSX__) +#if defined (__LINUX__) || (__MAC_OSX__) //Don't make the following code conditional on windows //(Addresses a weird timing bug when in hub client mode) if (!mPeerAddress.setAddress(peerHostOrIP)) { @@ -113,7 +113,7 @@ void UdpDataProtocol::setPeerAddress(const char* peerHostOrIP) throw(std::invali } //cout << "UdpDataProtocol::setPeerAddress IP Address Number: " // << mPeerAddress.toString().toStdString() << endl; -#if defined (__LINUX__) || (__MAC__OSX__) +#if defined (__LINUX__) || (__MAC_OSX__) } #endif @@ -151,9 +151,9 @@ void UdpDataProtocol::setPeerAddress(const char* peerHostOrIP) throw(std::invali } #if defined (__WIN_32__) -void UdpDataProtocol::setSocket(SOCKET &socket) throw(std::runtime_error) +void UdpDataProtocol::setSocket(SOCKET &socket) #else -void UdpDataProtocol::setSocket(int &socket) throw(std::runtime_error) +void UdpDataProtocol::setSocket(int &socket) #endif { //If we haven't been passed a valid socket, then we should bind one. @@ -176,9 +176,9 @@ void UdpDataProtocol::setSocket(int &socket) throw(std::runtime_error) //******************************************************************************* #if defined (__WIN_32__) -SOCKET UdpDataProtocol::bindSocket() throw(std::runtime_error) +SOCKET UdpDataProtocol::bindSocket() #else -int UdpDataProtocol::bindSocket() throw(std::runtime_error) +int UdpDataProtocol::bindSocket() #endif { QMutexLocker locker(&sUdpMutex); @@ -188,7 +188,7 @@ int UdpDataProtocol::bindSocket() throw(std::runtime_error) WSADATA wsaData; int err; - wVersionRequested = MAKEWORD( 1, 1 ); + wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { @@ -200,8 +200,8 @@ int UdpDataProtocol::bindSocket() throw(std::runtime_error) // Confirm that the Windows Sockets DLL supports 1.1. or higher - if ( LOBYTE( wsaData.wVersion ) != 1 || - HIBYTE( wsaData.wVersion ) != 1 ) { + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 2 ) { // Tell the user that we couldn't find a useable // winsock.dll. WSACleanup( ); @@ -535,6 +535,11 @@ void UdpDataProtocol::run() uint16_t current_seq_num = 0; // Store current sequence number uint16_t last_seq_num = 0; // Store last package sequence number uint16_t newer_seq_num = 0; // Store newer sequence number + mTotCount = 0; + mLostCount = 0; + mOutOfOrderCount = 0; + mRevivedCount = 0; + mStatCount = 0; if (gVerboseFlag) std::cout << "step 8" << std::endl; while ( !mStopped ) @@ -571,9 +576,6 @@ void UdpDataProtocol::run() break; } case SENDER : { - //Make sure we don't start sending packets too soon. - QThread::msleep(100); - //----------------------------------------------------------------------------------- while ( !mStopped ) { // OLD CODE WITHOUT REDUNDANCY ----------------------------------------------------- @@ -632,7 +634,7 @@ void UdpDataProtocol::printUdpWaitedTooLong(int wait_msec) { int wait_time = 30; // msec if ( !(wait_msec%wait_time) ) { - std::cerr << "UDP waiting too long (more than " << wait_time << "ms)..." << endl; + std::cerr << "UDP waiting too long (more than " << wait_time << "ms) for " << mPeerAddress.toString().toStdString() << "..." << endl; } } @@ -655,6 +657,18 @@ void UdpDataProtocol::receivePacketRedundancy(QUdpSocket& UdpSocket, mJackTrip->getPeerSequenceNumber(full_redundant_packet); current_seq_num = newer_seq_num; + if (0 != last_seq_num) { + int16_t lost = newer_seq_num - last_seq_num - 1; + if (0 > lost) { + // Out of order packet, should be ignored + ++mOutOfOrderCount; + return; + } + else if (0 != lost) { + mLostCount += lost; + } + mTotCount += 1 + lost; + } //cout << current_seq_num << " "; int redun_last_index = 0; @@ -670,6 +684,7 @@ void UdpDataProtocol::receivePacketRedundancy(QUdpSocket& UdpSocket, mJackTrip->getPeerSequenceNumber( full_redundant_packet + (i*full_packet_size) ); //cout << current_seq_num << " "; } + mRevivedCount += redun_last_index; //cout << endl; last_seq_num = newer_seq_num; // Save last read packet @@ -684,6 +699,22 @@ void UdpDataProtocol::receivePacketRedundancy(QUdpSocket& UdpSocket, } } +//******************************************************************************* +bool UdpDataProtocol::getStats(DataProtocol::PktStat* stat) +{ + if (0 == mStatCount) { + mLostCount = 0; + mOutOfOrderCount = 0; + mRevivedCount = 0; + } + stat->tot = mTotCount; + stat->lost = mLostCount; + stat->outOfOrder = mOutOfOrderCount; + stat->revived = mRevivedCount; + stat->statCount = mStatCount++; + return true; +} + //******************************************************************************* void UdpDataProtocol::sendPacketRedundancy(int8_t* full_redundant_packet, int full_redundant_packet_size, diff --git a/src/UdpDataProtocol.h b/src/UdpDataProtocol.h index 2d09fe3..13d58f9 100644 --- a/src/UdpDataProtocol.h +++ b/src/UdpDataProtocol.h @@ -87,12 +87,12 @@ public: /** \brief Set the Peer address to connect to * \param peerHostOrIP IPv4 number or host name */ - void setPeerAddress(const char* peerHostOrIP) throw(std::invalid_argument); + void setPeerAddress(const char* peerHostOrIP); #if defined (__WIN_32__) - void setSocket(SOCKET &socket) throw(std::runtime_error); + void setSocket(SOCKET &socket); #else - void setSocket(int &socket) throw(std::runtime_error); + void setSocket(int &socket); #endif /** \brief Receives a packet. It blocks until a packet is received @@ -142,6 +142,7 @@ public: */ virtual void run(); + virtual bool getStats(PktStat* stat); private slots: void printUdpWaitedTooLong(int wait_msec); @@ -160,9 +161,9 @@ protected: /** \brief Binds the UDP socket to the available address and specified port */ #if defined (__WIN_32__) - SOCKET bindSocket() throw(std::runtime_error); + SOCKET bindSocket(); #else - int bindSocket() throw(std::runtime_error); + int bindSocket(); #endif /** \brief This function blocks until data is available for reading in the @@ -214,6 +215,12 @@ private: unsigned int mUdpRedundancyFactor; ///< Factor of redundancy static QMutex sUdpMutex; ///< Mutex to make thread safe the binding process + + std::atomic mTotCount; + std::atomic mLostCount; + std::atomic mOutOfOrderCount; + std::atomic mRevivedCount; + uint32_t mStatCount; }; #endif // __UDPDATAPROTOCOL_H__ diff --git a/src/UdpMasterListener.cpp b/src/UdpHubListener.cpp similarity index 89% rename from src/UdpMasterListener.cpp rename to src/UdpHubListener.cpp index 3c17676..b69b7b1 100644 --- a/src/UdpMasterListener.cpp +++ b/src/UdpHubListener.cpp @@ -30,7 +30,7 @@ //***************************************************************** /** - * \file UdpMasterListener.cpp + * \file UdpHubListener.cpp * \author Juan-Pablo Caceres and Chris Chafe * \date September 2008 */ @@ -45,7 +45,7 @@ #include #include -#include "UdpMasterListener.h" +#include "UdpHubListener.h" #include "JackTripWorker.h" #include "jacktrip_globals.h" @@ -53,7 +53,7 @@ using std::cout; using std::endl; //******************************************************************************* -UdpMasterListener::UdpMasterListener(int server_port) : +UdpHubListener::UdpHubListener(int server_port) : //mJTWorker(NULL), mServerPort(server_port), mStopped(false), @@ -70,6 +70,9 @@ UdpMasterListener::UdpMasterListener(int server_port) : mJTWorkers->insert(i, NULL); } + qDebug() << "mThreadPool default maxThreadCount =" << mThreadPool.maxThreadCount(); + mThreadPool.setMaxThreadCount(mThreadPool.maxThreadCount() * 16); + qDebug() << "mThreadPool maxThreadCount set to" << mThreadPool.maxThreadCount(); //mJTWorkers = new JackTripWorker(this); mThreadPool.setExpiryTimeout(3000); // msec (-1) = forever @@ -91,7 +94,7 @@ UdpMasterListener::UdpMasterListener(int server_port) : //******************************************************************************* -UdpMasterListener::~UdpMasterListener() +UdpHubListener::~UdpHubListener() { QMutexLocker lock(&mMutex); mThreadPool.waitForDone(); @@ -108,7 +111,7 @@ UdpMasterListener::~UdpMasterListener() // the client is already on the thread pool, it means that a new connection is // requested (the old was desconnected). So we have to remove that thread from // the pool and then connect again. -void UdpMasterListener::run() +void UdpHubListener::run() { mStopped = false; @@ -131,9 +134,14 @@ void UdpMasterListener::run() while ( !mStopped ) { cout << "JackTrip HUB SERVER: Waiting for client connections..." << endl; - cout << "JackTrip HUB SERVER: Hub auto audio patch setting = " << mHubPatch << endl; + if(m_connectDefaultAudioPorts) + { + cout << "JackTrip HUB SERVER: Hub auto audio patch setting = " << mHubPatch << endl; + } else { + cout << "JackTrip HUB SERVER: Hub auto audio patch disabled " << endl; + } cout << "=======================================================" << endl; - while ( !TcpServer.waitForNewConnection(1000) ) + while ( !TcpServer.hasPendingConnections() && !TcpServer.waitForNewConnection(1000) ) { if (mStopped) { return; } } // block until a new connection is received cout << "JackTrip HUB SERVER: Client Connection Received!" << endl; @@ -208,7 +216,7 @@ void UdpMasterListener::run() m_connectDefaultAudioPorts ); /// \todo temp default to 1 channel - qDebug() << "mPeerAddress" << id << mActiveAddress[id].address << mActiveAddress[id].port; +// qDebug() << "mPeerAddress" << id << mActiveAddress[id].address << mActiveAddress[id].port; } //send one thread to the pool cout << "JackTrip HUB SERVER: Starting JackTripWorker..." << endl; @@ -223,7 +231,7 @@ void UdpMasterListener::run() if (isWAIR()) connectMesh(true); // invoked with -Sw #endif // endwhere - qDebug() << "mPeerAddress" << mActiveAddress[id].address << mActiveAddress[id].port; +// qDebug() << "mPeerAddress" << mActiveAddress[id].address << mActiveAddress[id].port; connectPatch(true); } @@ -231,12 +239,12 @@ void UdpMasterListener::run() /* // Create objects on the stack - QUdpSocket MasterUdpSocket; + QUdpSocket HubUdpSocket; QHostAddress PeerAddress; uint16_t peer_port; // Ougoing Peer port, in case they're not using the default // Bind the socket to the well known port - bindUdpSocket(MasterUdpSocket, mServerPort); + bindUdpSocket(HubUdpSocket, mServerPort); char buf[1]; cout << "Server Listening in UDP Port: " << mServerPort << endl; @@ -245,11 +253,11 @@ void UdpMasterListener::run() while ( !mStopped ) { //cout << "WAITING........................." << endl; - while ( MasterUdpSocket.hasPendingDatagrams() ) + while ( HubUdpSocket.hasPendingDatagrams() ) { cout << "Received request from Client!" << endl; // Get Client IP Address and outgoing port from packet - int rv = MasterUdpSocket.readDatagram(buf, 1, &PeerAddress, &peer_port); + int rv = HubUdpSocket.readDatagram(buf, 1, &PeerAddress, &peer_port); cout << "Peer Port in Server ==== " << peer_port << endl; if (rv < 0) { std::cerr << "ERROR: Bad UDP packet read..." << endl; } @@ -283,7 +291,7 @@ void UdpMasterListener::run() //******************************************************************************* // Returns 0 on error -int UdpMasterListener::readClientUdpPort(QTcpSocket* clientConnection) +int UdpHubListener::readClientUdpPort(QTcpSocket* clientConnection) { // Read the size of the package // ---------------------------- @@ -309,7 +317,7 @@ int UdpMasterListener::readClientUdpPort(QTcpSocket* clientConnection) //******************************************************************************* -int UdpMasterListener::sendUdpPort(QTcpSocket* clientConnection, int udp_port) +int UdpHubListener::sendUdpPort(QTcpSocket* clientConnection, int udp_port) { // Send Port Number to Client // -------------------------- @@ -331,7 +339,7 @@ int UdpMasterListener::sendUdpPort(QTcpSocket* clientConnection, int udp_port) //******************************************************************************* /* -void UdpMasterListener::sendToPoolPrototype(int id) +void UdpHubListener::sendToPoolPrototype(int id) { mJTWorker->setJackTrip(id, mActiveAddress[id][0], mBasePort+(2*id), mActiveAddress[id][1], @@ -342,7 +350,7 @@ void UdpMasterListener::sendToPoolPrototype(int id) //******************************************************************************* -void UdpMasterListener::bindUdpSocket(QUdpSocket& udpsocket, int port) throw(std::runtime_error) +void UdpHubListener::bindUdpSocket(QUdpSocket& udpsocket, int port) { // QHostAddress::Any : let the kernel decide the active address if ( !udpsocket.bind(QHostAddress::Any, @@ -359,7 +367,7 @@ void UdpMasterListener::bindUdpSocket(QUdpSocket& udpsocket, int port) throw(std //******************************************************************************* // check by comparing 32-bit addresses -int UdpMasterListener::isNewAddress(QString address, uint16_t port) +int UdpHubListener::isNewAddress(QString address, uint16_t port) { QMutexLocker lock(&mMutex); bool busyAddress = false; @@ -404,7 +412,7 @@ int UdpMasterListener::isNewAddress(QString address, uint16_t port) //******************************************************************************* -int UdpMasterListener::getPoolID(QString address, uint16_t port) +int UdpHubListener::getPoolID(QString address, uint16_t port) { QMutexLocker lock(&mMutex); //for (int id = 0; id #include @@ -53,24 +53,25 @@ #include "jacktrip_types.h" #include "jacktrip_globals.h" class JackTripWorker; // forward declaration +class Settings; typedef struct { QString address; int16_t port; } addressPortPair; -/** \brief Master UDP listener on the Server. +/** \brief Hub UDP listener on the Server. * * This creates a server that will listen on the well know port (the server port) and will * spawn JackTrip threads into the Thread pool. Clients request a connection. */ -class UdpMasterListener : public QThread +class UdpHubListener : public QThread { Q_OBJECT; public: - UdpMasterListener(int server_port = gServerUdpPort); - virtual ~UdpMasterListener(); + UdpHubListener(int server_port = gServerUdpPort); + virtual ~UdpHubListener(); /// \brief Implements the Thread Loop. To start the thread, call start() /// ( DO NOT CALL run() ) @@ -83,6 +84,9 @@ public: void setConnectDefaultAudioPorts(bool connectDefaultAudioPorts) { m_connectDefaultAudioPorts = connectDefaultAudioPorts; } + void setSettings(Settings* s) {m_settings = s;} + Settings* getSettings() const {return m_settings;} + private slots: void testReceive() { std::cout << "========= TEST RECEIVE SLOT ===========" << std::endl; } @@ -98,7 +102,7 @@ private: * \param udpsocket a QUdpSocket * \param port Port number */ - static void bindUdpSocket(QUdpSocket& udpsocket, int port) throw(std::runtime_error); + static void bindUdpSocket(QUdpSocket& udpsocket, int port); int readClientUdpPort(QTcpSocket* clientConnection); int sendUdpPort(QTcpSocket* clientConnection, int udp_port); @@ -121,7 +125,7 @@ private: */ int getPoolID(QString address, uint16_t port); - //QUdpSocket mUdpMasterSocket; ///< The UDP socket + //QUdpSocket mUdpHubSocket; ///< The UDP socket //QHostAddress mPeerAddress; ///< The Peer Address //JackTripWorker* mJTWorker; ///< Class that will be used as prototype @@ -141,6 +145,7 @@ private: int mBufferQueueLength; bool m_connectDefaultAudioPorts; + Settings* m_settings; #ifdef WAIR // wair bool mWAIR; @@ -161,4 +166,4 @@ public : }; -#endif //__UDPMASTERLISTENER_H__ +#endif //__UDPHUBLISTENER_H__ diff --git a/src/build b/src/build index 15011b4..e3f7150 100755 --- a/src/build +++ b/src/build @@ -17,9 +17,6 @@ if [[ $platform == 'linux' ]]; then if hash qmake-qt5 2>/dev/null; then echo "Using qmake-qt5" QCMD=qmake-qt5 - elif hash qmake-qt4 2>/dev/null; then - echo "Using qmake-qt4" - QCMD=qmake-qt4 elif hash qmake 2>/dev/null; then #in case qt was compiled by user echo "Using qmake" QCMD=qmake @@ -31,15 +28,17 @@ elif [[ $platform == 'macosx' ]]; then fi # Build +mkdir -p ../builddir +cd ../builddir if [[ $1 == 'nojack' ]]; then echo "Building without Jack" - $QCMD -spec $QSPEC -config nojack jacktrip.pro + $QCMD -spec $QSPEC -config nojack ../src/jacktrip.pro make clean - $QCMD -spec $QSPEC -config nojack jacktrip.pro + $QCMD -spec $QSPEC -config nojack ../src/jacktrip.pro make release else - $QCMD -spec $QSPEC jacktrip.pro + $QCMD -spec $QSPEC ../src/jacktrip.pro make clean - $QCMD -spec $QSPEC jacktrip.pro + $QCMD -spec $QSPEC ../src/jacktrip.pro make release fi diff --git a/src/jacktrip.pro b/src/jacktrip.pro index 590419f..f898c63 100644 --- a/src/jacktrip.pro +++ b/src/jacktrip.pro @@ -15,9 +15,9 @@ CONFIG(debug, debug|release) { QT -= gui QT += network -# rc.1.2 switch enables experimental wair build, merge some of it with WAIRTOMASTER +# rc.1.2 switch enables experimental wair build, merge some of it with WAIRTOHUB # DEFINES += WAIR -DEFINES += WAIRTOMASTER +DEFINES += WAIRTOHUB # http://wiki.qtcentre.org/index.php?title=Undocumented_qmake#Custom_tools #cc DEFINES += __RT_AUDIO__ @@ -135,7 +135,7 @@ HEADERS += DataProtocol.h \ TestRingBuffer.h \ ThreadPoolTest.h \ UdpDataProtocol.h \ - UdpMasterListener.h \ + UdpHubListener.h \ AudioInterface.h !nojack { @@ -155,7 +155,7 @@ SOURCES += DataProtocol.cpp \ RingBuffer.cpp \ Settings.cpp \ UdpDataProtocol.cpp \ - UdpMasterListener.cpp \ + UdpHubListener.cpp \ AudioInterface.cpp !nojack { diff --git a/src/jacktrip_globals.h b/src/jacktrip_globals.h index 9f31e6a..e0dfa08 100644 --- a/src/jacktrip_globals.h +++ b/src/jacktrip_globals.h @@ -44,7 +44,7 @@ /// \todo Add this namespace //namespace JackTrip -const char* const gVersion = "1.2beta2"; ///< JackTrip version +const char* const gVersion = "1.2.1"; ///< JackTrip version //******************************************************************************* /// \name Default Values @@ -55,7 +55,8 @@ const int gDefaultNumOutChannels = 2; #define PROTOCOL_STACK QHostAddress::AnyIPv4 // as opposed to Any // #define WAIR_AUDIO_NAME "JackTrip" // for jack connection const QString WAIR_AUDIO_NAME = QString("JackTrip"); // keep legacy for WAIR -const int gMAX_WAIRS = 10; // jmess revision needed for string parse if > 1 digit +const int gMAX_WAIRS = 128; // FIXME, should agree with maxThreadCount +// jmess revision needed for string parse if > 1 digit // hubpatch = 3 for TUB ensemble patching /////////////////////////////// @@ -89,7 +90,7 @@ const uint32_t gDefaultDeviceID = 0; const uint32_t gDefaultBufferSizeInSamples = 128; const QString gDefaultLocalAddress = QString(); const int gDefaultRedundancy = 1; -const int gTimeOutMultiThreadedServer = 5000; // seconds +const int gTimeOutMultiThreadedServer = 10000; // seconds const int gWaitCounter = 60; //@} @@ -122,6 +123,7 @@ extern int gVerboseFlag; ///< Verbose mode flag declaration /// \name JackAudio //@{ const int gJackBitResolution = 32; ///< Audio Bit Resolution of the Jack Server +const char* const gJackDefaultClientName = "JackTrip"; //@} @@ -135,7 +137,7 @@ void setRealtimeProcessPriority(); /// \name JackTrip Server parameters //@{ /// Maximum Threads that can be run at the same time -const int gMaxThreads = 290; // some pthread limit around 297? +const int gMaxThreads = 1024; /// Public well-known UDP port to where the clients will connect const int gServerUdpPort = 4464; -- 2.30.2