Merge pull request #229 from pljones/feature/170-allow-triggered-recording-cuts

Feature/170 allow triggered recording cuts
This commit is contained in:
Volker Fischer 2020-05-16 09:20:47 +02:00 committed by GitHub
commit e529baeb94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 120 additions and 35 deletions

View file

@ -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() ); 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() ), QObject::connect( (const QObject *)server, SIGNAL ( Stopped() ),
this, SLOT( OnEnd() ), this, SLOT( OnEnd() ),
Qt::ConnectionType::QueuedConnection ); Qt::ConnectionType::QueuedConnection );
@ -322,13 +326,12 @@ void CJamRecorder::Init( const CServer* server,
this, SLOT( OnDisconnected ( int ) ), this, SLOT( OnDisconnected ( int ) ),
Qt::ConnectionType::QueuedConnection ); Qt::ConnectionType::QueuedConnection );
qRegisterMetaType<CVector<int16_t>>(); qRegisterMetaType<CVector<int16_t>> ( "CVector<int16_t>" );
QObject::connect( (const QObject *)server, SIGNAL ( AudioFrame( const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ), QObject::connect( (const QObject *)server, SIGNAL ( AudioFrame( const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ),
this, SLOT( OnFrame (const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ), this, SLOT( OnFrame (const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ),
Qt::ConnectionType::QueuedConnection ); Qt::ConnectionType::QueuedConnection );
QObject::connect( QCoreApplication::instance(), QObject::connect( QCoreApplication::instance(), SIGNAL ( aboutToQuit() ),
SIGNAL ( aboutToQuit() ),
this, SLOT( OnAboutToQuit() ) ); this, SLOT( OnAboutToQuit() ) );
iServerFrameSizeSamples = _iServerFrameSizeSamples; iServerFrameSizeSamples = _iServerFrameSizeSamples;
@ -338,11 +341,10 @@ void CJamRecorder::Init( const CServer* server,
thisThread->start(); 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. // Ensure any previous cleaning up has been done.
OnEnd(); OnEnd();
@ -350,11 +352,17 @@ void CJamRecorder::OnStart() {
isRecording = true; isRecording = true;
} }
/** /**
* @brief CJamRecorder::OnEnd Finalise the recording and emit the Reaper RPP file * @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() void CJamRecorder::OnEnd()
{ {
QString reaperProjectFileName = QString::Null();
if ( isRecording ) if ( isRecording )
{ {
isRecording = false; isRecording = false;
@ -366,21 +374,46 @@ void CJamRecorder::OnEnd()
if (fi.exists()) if (fi.exists())
{ {
qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "exists and will not be overwritten."; qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "exists and will not be overwritten.";
reaperProjectFileName = QString::Null();
} }
else else
{ {
QFile outf (reaperProjectFileName); QFile outf (reaperProjectFileName);
outf.open(QFile::WriteOnly); if ( outf.open(QFile::WriteOnly) )
QTextStream out(&outf); {
out << CReaperProject( currentSession->Tracks(), iServerFrameSizeSamples ).toString() << endl; QTextStream out(&outf);
qDebug() << "Session RPP:" << reaperProjectFileName; 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; delete currentSession;
currentSession = nullptr; 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() void CJamRecorder::OnAboutToQuit()
{ {
OnEnd(); OnEnd();
@ -452,7 +485,7 @@ void CJamRecorder::OnFrame(const int iChID, const QString name, const CHostAddre
// Make sure we are ready // Make sure we are ready
if ( !isRecording ) if ( !isRecording )
{ {
OnStart(); Start();
} }
currentSession->Frame( iChID, name, address, numAudioChannels, data, iServerFrameSizeSamples ); currentSession->Frame( iChID, name, address, numAudioChannels, data, iServerFrameSizeSamples );

View file

@ -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 ); 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 ); static void SessionDirToReaper( QString& strSessionDirName, int serverFrameSizeSamples );
public slots: private:
/** void Start();
* @brief Raised when first client joins the server, triggering a new recording.
*/
void OnStart();
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. * @brief Raised when last client leaves the server, ending the recording.
*/ */
void OnEnd(); void OnEnd();
/**
* @brief Raised to end one session and start a new one.
*/
void OnTriggerSession();
/** /**
* @brief Raised when application is stopping * @brief Raised when application is stopping
*/ */
@ -173,15 +196,6 @@ public slots:
* @brief Raised when a frame of data is available to process * @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<int16_t> data ); void OnFrame ( const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector<int16_t> data );
private:
QDir recordBaseDir;
bool isRecording;
CJamSession* currentSession;
int iServerFrameSizeSamples;
QThread* thisThread;
}; };
} }

View file

@ -471,8 +471,8 @@ CServer::CServer ( const int iNewMaxNumChan,
this, SLOT ( OnAboutToQuit() ) ); this, SLOT ( OnAboutToQuit() ) );
QObject::connect ( pSignalHandler, QObject::connect ( pSignalHandler,
SIGNAL ( ShutdownSignal ( int ) ), SIGNAL ( HandledSignal ( int ) ),
this, SLOT ( OnShutdown ( int ) ) ); this, SLOT ( OnHandledSignal ( int ) ) );
connectChannelSignalsToServerSlots<MAX_NUM_CHANNELS>(); connectChannelSignalsToServerSlots<MAX_NUM_CHANNELS>();
@ -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(); 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() void CServer::Start()
@ -1565,3 +1590,11 @@ void CServer::CreateLevelsForAllConChannels ( const int i
vecLevelsOut[j] = static_cast<uint16_t> ( ceil ( dCurSigLevel ) ); vecLevelsOut[j] = static_cast<uint16_t> ( ceil ( dCurSigLevel ) );
} }
} }
void CServer::RequestNewRecording()
{
if ( bEnableRecording )
{
emit RestartRecorder();
}
}

View file

@ -285,6 +285,8 @@ protected:
const CVector<CVector<int16_t> > vecvecsData, const CVector<CVector<int16_t> > vecvecsData,
CVector<uint16_t>& vecLevelsOut ); CVector<uint16_t>& vecLevelsOut );
void RequestNewRecording();
// do not use the vector class since CChannel does not have appropriate // do not use the vector class since CChannel does not have appropriate
// copy constructor/operator // copy constructor/operator
CChannel vecChannels[MAX_NUM_CHANNELS]; CChannel vecChannels[MAX_NUM_CHANNELS];
@ -364,6 +366,7 @@ signals:
const CHostAddress RecHostAddr, const CHostAddress RecHostAddr,
const int iNumAudChan, const int iNumAudChan,
const CVector<int16_t> vecsData ); const CVector<int16_t> vecsData );
void RestartRecorder();
public slots: public slots:
void OnTimer(); void OnTimer();
@ -441,5 +444,5 @@ public slots:
void OnAboutToQuit(); void OnAboutToQuit();
void OnShutdown ( int ); void OnHandledSignal ( int sigNum );
}; };

View file

@ -75,7 +75,7 @@ CSignalHandler* CSignalHandler::getSingletonP() { return singleton; }
bool CSignalHandler::emitSignal ( int sigNum ) 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 #ifndef _WIN32
@ -124,11 +124,11 @@ QReadWriteLock* CSignalWin::getLock() const
return &lock; return &lock;
} }
BOOL WINAPI CSignalWin::signalHandler ( _In_ DWORD sigNum ) BOOL WINAPI CSignalWin::signalHandler ( _In_ DWORD )
{ {
auto self = getSelf<CSignalWin>(); auto self = getSelf<CSignalWin>();
QReadLocker lock ( self->getLock() ); QReadLocker lock ( self->getLock() );
return self->pSignalHandler->emitSignal ( static_cast<int>( sigNum ) ); return self->pSignalHandler->emitSignal ( -1 );
} }
#else #else
@ -145,12 +145,14 @@ CSignalUnix::CSignalUnix ( CSignalHandler* nPSignalHandler ) :
socketNotifier->setEnabled ( true ); socketNotifier->setEnabled ( true );
setSignalHandled ( SIGUSR1, true );
setSignalHandled ( SIGINT, true ); setSignalHandled ( SIGINT, true );
setSignalHandled ( SIGTERM, true ); setSignalHandled ( SIGTERM, true );
} }
} }
CSignalUnix::~CSignalUnix() { CSignalUnix::~CSignalUnix() {
setSignalHandled ( SIGUSR1, false );
setSignalHandled ( SIGINT, false ); setSignalHandled ( SIGINT, false );
setSignalHandled ( SIGTERM, false ); setSignalHandled ( SIGTERM, false );
} }

View file

@ -104,7 +104,7 @@ public slots:
#endif #endif
signals: signals:
void ShutdownSignal ( int sigNum ); void HandledSignal ( int sigNum );
private: private:
QScopedPointer<CSignalBase> pSignalBase; QScopedPointer<CSignalBase> pSignalBase;
@ -153,7 +153,7 @@ public:
private: private:
mutable QReadWriteLock lock; mutable QReadWriteLock lock;
static BOOL WINAPI signalHandler ( _In_ DWORD sigNum ); static BOOL WINAPI signalHandler ( _In_ DWORD );
}; };
#else #else