diff --git a/src/recorder/jamrecorder.cpp b/src/recorder/jamrecorder.cpp index 2c817919..4327ccf2 100755 --- a/src/recorder/jamrecorder.cpp +++ b/src/recorder/jamrecorder.cpp @@ -314,6 +314,10 @@ void CJamRecorder::Init( const CServer* server, throw std::runtime_error( (recordBaseDir.absolutePath() + " is a directory but cannot be written to").toStdString() ); } + QObject::connect( (const QObject *)server, SIGNAL ( RestartRecorder() ), + this, SLOT( OnTriggerSession() ), + Qt::ConnectionType::QueuedConnection ); + QObject::connect( (const QObject *)server, SIGNAL ( Stopped() ), this, SLOT( OnEnd() ), Qt::ConnectionType::QueuedConnection ); @@ -322,13 +326,12 @@ void CJamRecorder::Init( const CServer* server, this, SLOT( OnDisconnected ( int ) ), Qt::ConnectionType::QueuedConnection ); - qRegisterMetaType>(); + qRegisterMetaType> ( "CVector" ); QObject::connect( (const QObject *)server, SIGNAL ( AudioFrame( const int, const QString, const CHostAddress, const int, const CVector ) ), this, SLOT( OnFrame (const int, const QString, const CHostAddress, const int, const CVector ) ), Qt::ConnectionType::QueuedConnection ); - QObject::connect( QCoreApplication::instance(), - SIGNAL ( aboutToQuit() ), + QObject::connect( QCoreApplication::instance(), SIGNAL ( aboutToQuit() ), this, SLOT( OnAboutToQuit() ) ); iServerFrameSizeSamples = _iServerFrameSizeSamples; @@ -338,11 +341,10 @@ void CJamRecorder::Init( const CServer* server, thisThread->start(); } - /** - * @brief CJamRecorder::OnStart Start up tasks when the first client connects + * @brief CJamRecorder::Start Start up tasks for a new session */ -void CJamRecorder::OnStart() { +void CJamRecorder::Start() { // Ensure any previous cleaning up has been done. OnEnd(); @@ -350,11 +352,17 @@ void CJamRecorder::OnStart() { isRecording = true; } + /** * @brief CJamRecorder::OnEnd Finalise the recording and emit the Reaper RPP file + * + * Emits RecordingSessionEnded with the Reaper project file name, + * or null if was not recording or a problem occurs */ void CJamRecorder::OnEnd() { + QString reaperProjectFileName = QString::Null(); + if ( isRecording ) { isRecording = false; @@ -366,21 +374,46 @@ void CJamRecorder::OnEnd() if (fi.exists()) { qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "exists and will not be overwritten."; + reaperProjectFileName = QString::Null(); } else { QFile outf (reaperProjectFileName); - outf.open(QFile::WriteOnly); - QTextStream out(&outf); - out << CReaperProject( currentSession->Tracks(), iServerFrameSizeSamples ).toString() << endl; - qDebug() << "Session RPP:" << reaperProjectFileName; + if ( outf.open(QFile::WriteOnly) ) + { + QTextStream out(&outf); + out << CReaperProject( currentSession->Tracks(), iServerFrameSizeSamples ).toString() << endl; + qDebug() << "Session RPP:" << reaperProjectFileName; + } + else + { + qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "could not be created, no RPP written."; + reaperProjectFileName = QString::Null(); + } } delete currentSession; currentSession = nullptr; } + + emit RecordingSessionEnded ( reaperProjectFileName ); } +/** + * @brief CJamRecorder::OnTriggerSession End one session and start a new one + */ +void CJamRecorder::OnTriggerSession() +{ + // This should magically get everything right... + if ( isRecording ) + { + Start(); + } +} + +/** + * @brief CJamRecorder::OnAboutToQuit End any recording and exit thread + */ void CJamRecorder::OnAboutToQuit() { OnEnd(); @@ -452,7 +485,7 @@ void CJamRecorder::OnFrame(const int iChID, const QString name, const CHostAddre // Make sure we are ready if ( !isRecording ) { - OnStart(); + Start(); } currentSession->Frame( iChID, name, address, numAudioChannels, data, iServerFrameSizeSamples ); diff --git a/src/recorder/jamrecorder.h b/src/recorder/jamrecorder.h index eb5a0581..2bc128db 100755 --- a/src/recorder/jamrecorder.h +++ b/src/recorder/jamrecorder.h @@ -143,21 +143,44 @@ public: { } + /** + * @brief Create recording directory, if necessary, and connect signal handlers + * @param server Server object emiting signals + */ void Init( const CServer* server, const int _iServerFrameSizeSamples ); + /** + * @brief SessionDirToReaper Method that allows an RPP file to be recreated + * @param strSessionDirName Where the session wave files are + * @param serverFrameSizeSamples What the server frame size was for the session + */ static void SessionDirToReaper( QString& strSessionDirName, int serverFrameSizeSamples ); -public slots: - /** - * @brief Raised when first client joins the server, triggering a new recording. - */ - void OnStart(); +private: + void Start(); + QDir recordBaseDir; + + bool isRecording; + CJamSession* currentSession; + int iServerFrameSizeSamples; + + QThread* thisThread; + +signals: + void RecordingSessionEnded ( QString sessionDir ); + +private slots: /** * @brief Raised when last client leaves the server, ending the recording. */ void OnEnd(); + /** + * @brief Raised to end one session and start a new one. + */ + void OnTriggerSession(); + /** * @brief Raised when application is stopping */ @@ -173,15 +196,6 @@ public slots: * @brief Raised when a frame of data is available to process */ void OnFrame ( const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector data ); - -private: - QDir recordBaseDir; - - bool isRecording; - CJamSession* currentSession; - int iServerFrameSizeSamples; - - QThread* thisThread; }; } diff --git a/src/server.cpp b/src/server.cpp index 87af18bb..718875e8 100755 --- a/src/server.cpp +++ b/src/server.cpp @@ -471,8 +471,8 @@ CServer::CServer ( const int iNewMaxNumChan, this, SLOT ( OnAboutToQuit() ) ); QObject::connect ( pSignalHandler, - SIGNAL ( ShutdownSignal ( int ) ), - this, SLOT ( OnShutdown ( int ) ) ); + SIGNAL ( HandledSignal ( int ) ), + this, SLOT ( OnHandledSignal ( int ) ) ); connectChannelSignalsToServerSlots(); @@ -665,10 +665,35 @@ void CServer::OnAboutToQuit() } } -void CServer::OnShutdown ( int ) +void CServer::OnHandledSignal ( int sigNum ) { - // This should trigger OnAboutToQuit +#ifdef _WIN32 + + // Windows does not actually get OnHandledSignal triggered QCoreApplication::instance()->exit(); + Q_UNUSED ( sigNum ) + +#else + + switch ( sigNum ) + { + + case SIGUSR1: + RequestNewRecording(); + break; + + case SIGINT: + case SIGTERM: + // This should trigger OnAboutToQuit + QCoreApplication::instance()->exit(); + break; + + default: + break; + + } + +#endif } void CServer::Start() @@ -1565,3 +1590,11 @@ void CServer::CreateLevelsForAllConChannels ( const int i vecLevelsOut[j] = static_cast ( ceil ( dCurSigLevel ) ); } } + +void CServer::RequestNewRecording() +{ + if ( bEnableRecording ) + { + emit RestartRecorder(); + } +} diff --git a/src/server.h b/src/server.h index da38bc35..475928e4 100755 --- a/src/server.h +++ b/src/server.h @@ -285,6 +285,8 @@ protected: const CVector > vecvecsData, CVector& vecLevelsOut ); + void RequestNewRecording(); + // do not use the vector class since CChannel does not have appropriate // copy constructor/operator CChannel vecChannels[MAX_NUM_CHANNELS]; @@ -364,6 +366,7 @@ signals: const CHostAddress RecHostAddr, const int iNumAudChan, const CVector vecsData ); + void RestartRecorder(); public slots: void OnTimer(); @@ -441,5 +444,5 @@ public slots: void OnAboutToQuit(); - void OnShutdown ( int ); + void OnHandledSignal ( int sigNum ); }; diff --git a/src/signalhandler.cpp b/src/signalhandler.cpp index 4c37d018..d0205c9e 100755 --- a/src/signalhandler.cpp +++ b/src/signalhandler.cpp @@ -75,7 +75,7 @@ CSignalHandler* CSignalHandler::getSingletonP() { return singleton; } bool CSignalHandler::emitSignal ( int sigNum ) { - return QMetaObject::invokeMethod( singleton, "ShutdownSignal", Qt::QueuedConnection, Q_ARG( int, sigNum ) ); + return QMetaObject::invokeMethod( singleton, "HandledSignal", Qt::QueuedConnection, Q_ARG( int, sigNum ) ); } #ifndef _WIN32 @@ -124,11 +124,11 @@ QReadWriteLock* CSignalWin::getLock() const return &lock; } -BOOL WINAPI CSignalWin::signalHandler ( _In_ DWORD sigNum ) +BOOL WINAPI CSignalWin::signalHandler ( _In_ DWORD ) { auto self = getSelf(); QReadLocker lock ( self->getLock() ); - return self->pSignalHandler->emitSignal ( static_cast( sigNum ) ); + return self->pSignalHandler->emitSignal ( -1 ); } #else @@ -145,12 +145,14 @@ CSignalUnix::CSignalUnix ( CSignalHandler* nPSignalHandler ) : socketNotifier->setEnabled ( true ); + setSignalHandled ( SIGUSR1, true ); setSignalHandled ( SIGINT, true ); setSignalHandled ( SIGTERM, true ); } } CSignalUnix::~CSignalUnix() { + setSignalHandled ( SIGUSR1, false ); setSignalHandled ( SIGINT, false ); setSignalHandled ( SIGTERM, false ); } diff --git a/src/signalhandler.h b/src/signalhandler.h index 1263ee6a..59409d13 100755 --- a/src/signalhandler.h +++ b/src/signalhandler.h @@ -104,7 +104,7 @@ public slots: #endif signals: - void ShutdownSignal ( int sigNum ); + void HandledSignal ( int sigNum ); private: QScopedPointer pSignalBase; @@ -153,7 +153,7 @@ public: private: mutable QReadWriteLock lock; - static BOOL WINAPI signalHandler ( _In_ DWORD sigNum ); + static BOOL WINAPI signalHandler ( _In_ DWORD ); }; #else