Skip to content

Commit

Permalink
Merge pull request #1 from pljones/feature/pljones-audio-stream-saving
Browse files Browse the repository at this point in the history
Feature/pljones audio stream saving
  • Loading branch information
pljones authored Apr 3, 2019
2 parents 46d1d26 + 005a506 commit 8d6cfd8
Show file tree
Hide file tree
Showing 20 changed files with 1,128 additions and 22 deletions.
12 changes: 9 additions & 3 deletions Jamulus.pro
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ win32 {

!exists(/usr/include/jack/jack.h) {
!exists(/usr/local/include/jack/jack.h) {
message(Warning: jack.h was not found at the usual place, maybe the jack dev packet is missing)
message("Warning: jack.h was not found at the usual place, maybe the jack dev packet is missing")
}
}

Expand Down Expand Up @@ -170,7 +170,10 @@ HEADERS += src/audiomixerboard.h \
src/soundbase.h \
src/testbench.h \
src/util.h \
src/analyzerconsole.h
src/analyzerconsole.h \
src/recorder/jamrecorder.h \
src/recorder/creaperproject.h \
src/recorder/cwavestream.h

HEADERS_OPUS = libs/opus/include/opus.h \
libs/opus/include/opus_multistream.h \
Expand Down Expand Up @@ -264,7 +267,10 @@ SOURCES += src/audiomixerboard.cpp \
src/socket.cpp \
src/soundbase.cpp \
src/util.cpp \
src/analyzerconsole.cpp
src/analyzerconsole.cpp \
src/recorder/jamrecorder.cpp \
src/recorder/creaperproject.cpp \
src/recorder/cwavestream.cpp

SOURCES_OPUS = libs/opus/src/opus.c \
libs/opus/src/opus_decoder.c \
Expand Down
8 changes: 8 additions & 0 deletions src/chatdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,11 @@ void CChatDlg::AddChatText ( QString strChatText )
#endif
);
}

void CChatDlg::keyPressEvent(QKeyEvent *e)
{
if (e->key() != Qt::Key_Escape)
{
QDialog::keyPressEvent(e);
}
}
2 changes: 2 additions & 0 deletions src/chatdlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public slots:
void OnLocalInputTextTextChanged ( const QString& strNewText );
void OnClearPressed();

void keyPressEvent(QKeyEvent *e);

signals:
void NewLocalInputText ( QString strNewText );
};
13 changes: 13 additions & 0 deletions src/clientdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,3 +1200,16 @@ rbtReverbSelR->setStyleSheet ( "" );
// also apply GUI design to child GUI controls
MainMixerBoard->SetGUIDesign ( eNewDesign );
}

void CClientDlg::accept()
{
close();
}

void CClientDlg::keyPressEvent(QKeyEvent *e)
{
if (e->key() != Qt::Key_Escape)
{
QDialog::keyPressEvent(e);
}
}
3 changes: 3 additions & 0 deletions src/clientdlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,7 @@ public slots:
void OnAudioChannelsChanged() { UpdateRevSelection(); }
void OnNumClientsChanged ( int iNewNumClients );
void OnNewClientLevelChanged() { MainMixerBoard->iNewClientFaderLevel = pClient->iNewClientFaderLevel; }

void accept();
void keyPressEvent(QKeyEvent *e);
};
4 changes: 4 additions & 0 deletions src/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ LED bar: lbr
#if !defined ( GLOBAL_H__3B123453_4344_BB2B_23E7A0D31912__INCLUDED_ )
#define GLOBAL_H__3B123453_4344_BB2B_23E7A0D31912__INCLUDED_

#if _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <QString>
#include <QEvent>
#include <QDebug>
Expand Down
107 changes: 97 additions & 10 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,41 @@
#include "testbench.h"


// Implementation **************************************************************

int main ( int argc, char** argv )
/******************************************************************************\
* Console logging *
\******************************************************************************/
// Try for a portable console --------------------------------------------------

QTextStream* ConsoleWriterFactory::get()
{
#ifdef _WIN32
// no console on windows -> just write in string and dump it
QString strDummySink;
QTextStream tsConsole ( &strDummySink );
if (ptsConsole == nullptr)
{
#if _WIN32
if (!AttachConsole(ATTACH_PARENT_PROCESS))
{
// Not run from console, dump logging to nowhere
static QString conout;
ptsConsole = new QTextStream ( &conout );
}
else
{
freopen("CONOUT$", "w", stdout);
ptsConsole = new QTextStream ( stdout );
}
#else
QTextStream tsConsole ( stdout );
ptsConsole = new QTextStream ( stdout );
#endif
}
return ptsConsole;
}

// Implementation **************************************************************

int main ( int argc, char** argv )
{
QTextStream& tsConsole = *((new ConsoleWriterFactory())->get());

QString strArgument;
double rDbleArgument;

Expand All @@ -56,6 +80,7 @@ int main ( int argc, char** argv )
bool bDisconnectAllClients = false;
bool bShowAnalyzerConsole = false;
bool bCentServPingServerInList = false;
bool bEnableRecording = false;
int iNumServerChannels = DEFAULT_USED_NUM_CHANNELS;
int iCtrlMIDIChannel = INVALID_MIDI_CH;
quint16 iPortNumber = LLCON_DEFAULT_PORT_NUMBER;
Expand All @@ -66,6 +91,8 @@ int main ( int argc, char** argv )
QString strServerName = "";
QString strLoggingFileName = "";
QString strHistoryFileName = "";
QString strRecordingDirName = "";
QString strSessionDirName = "";
QString strCentralServer = "";
QString strServerInfo = "";
QString strWelcomeMessage = "";
Expand Down Expand Up @@ -157,6 +184,18 @@ int main ( int argc, char** argv )
}


// Enable recording at the server --------------------------------------
if ( GetFlagArgument ( argv,
i,
"-r",
"--enablerecording" ) )
{
bEnableRecording = true;
tsConsole << "- enabling recording" << endl;
continue;
}


// Show all registered servers in the server list ----------------------
// Undocumented debugging command line argument: Show all registered
// servers in the server list regardless if a ping to the server is
Expand Down Expand Up @@ -292,6 +331,37 @@ int main ( int argc, char** argv )
}


// Recording directory -------------------------------------------------
if ( GetStringArgument ( tsConsole,
argc,
argv,
i,
"-R",
"--recordingdirectory",
strArgument ) )
{
strRecordingDirName = strArgument;
tsConsole << "- recording directory name: " << strRecordingDirName << endl;
continue;
}


// Convert a recording session to a Reaper Project ---------------------
if ( GetStringArgument ( tsConsole,
argc,
argv,
i,
"-T",
"--toreaper",
strArgument ) )
{
bUseGUI = false;
strSessionDirName = strArgument;
tsConsole << "- convert " << strSessionDirName << " to Reaper project (no GUI)" << endl;
continue;
}


// Central server ------------------------------------------------------
if ( GetStringArgument ( tsConsole,
argc,
Expand Down Expand Up @@ -402,7 +472,15 @@ int main ( int argc, char** argv )

// Application/GUI setup ---------------------------------------------------
// Application object
QApplication app ( argc, argv, bUseGUI );
if (!bUseGUI && !strHistoryFileName.isEmpty())
{
tsConsole << "Qt5 requires a windowing system to paint a JPEG image; disabling history graph" << endl;
strHistoryFileName = "";
}
QCoreApplication* _app = bUseGUI
? new QApplication ( argc, argv )
: new QCoreApplication ( argc, argv );
#define app (*_app)

#ifdef _WIN32
// set application priority class -> high priority
Expand All @@ -425,7 +503,11 @@ int main ( int argc, char** argv )

try
{
if ( bIsClient )
if ( !strSessionDirName.isEmpty() )
{
CJamRecorder::SessionDirToReaper(strSessionDirName);
}
else if ( bIsClient )
{
// Client:
// actual client object
Expand Down Expand Up @@ -473,10 +555,11 @@ int main ( int argc, char** argv )
strCentralServer,
strServerInfo,
strWelcomeMessage,
strRecordingDirName,
bEnableRecording,
bCentServPingServerInList,
bDisconnectAllClients,
eLicenceType );

if ( bUseGUI )
{
// special case for the GUI mode: as the default we want to use
Expand Down Expand Up @@ -571,7 +654,11 @@ QString UsageArguments ( char **argv )
" [server1 country as QLocale ID]; ...\n"
" [server2 address]; ... (server only)\n"
" -p, --port local port number (server only)\n"
" -r --enablerecording create recordings of jam sessions (server only)\n"
" -R, --recordingdirectory\n"
" directory to contain recorded jams (server only)\n"
" -s, --server start server\n"
" -T, --toreaper create Reaper project from session in named directory\n"
" -u, --numchannels maximum number of channels (server only)\n"
" -w, --welcomemessage welcome message on connect (server only)\n"
" -y, --history enable connection history and set file\n"
Expand Down
107 changes: 107 additions & 0 deletions src/recorder/creaperproject.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include "creaperproject.h"

/**
* @brief operator << Write details of the STrackItem to the QTextStream
* @param os the QTextStream
* @param trackItem the STrackItem
* @return the QTextStream
*
* Note: unused?
*/
QTextStream& operator<<(QTextStream& os, const recorder::STrackItem& trackItem)
{
os << "_track( "
<< "numAudioChannels(" << trackItem.numAudioChannels << ")"
<< ", startFrame(" << trackItem.startFrame << ")"
<< ", frameCount(" << trackItem.frameCount << ")"
<< ", fileName(" << trackItem.fileName << ")"
<< " );";
return os;
}

/******************************************************************************\
* recorder methods *
\******************************************************************************/
using namespace recorder;

// Reaper Project writer -------------------------------------------------------

/**
* @brief CReaperItem::CReaperItem Construct a Reaper RPP "<ITEM>" for a given RIFF WAVE file
* @param name the item name
* @param trackItem the details of where the item is in the track, along with the RIFF WAVE filename
* @param iid the sequential item id
*/
CReaperItem::CReaperItem(const QString& name, const STrackItem& trackItem, const qint32& iid)
{
QString wavName = trackItem.fileName; // assume RPP in same location...

QTextStream sOut(&out);

sOut << " <ITEM " << endl;
sOut << " FADEIN 0 0 0 0 0 0" << endl;
sOut << " FADEOUT 0 0 0 0 0 0" << endl;
sOut << " POSITION " << secondsAt48K(trackItem.startFrame) << endl;
sOut << " LENGTH " << secondsAt48K(trackItem.frameCount) << endl;
sOut << " IGUID " << iguid.toString() << endl;
sOut << " IID " << iid << endl;
sOut << " NAME " << name << endl;
sOut << " GUID " << guid.toString() << endl;

sOut << " <SOURCE WAVE" << endl;
sOut << " FILE " << '"' << wavName << '"' << endl;
sOut << " >" << endl;

sOut << " >";

sOut.flush();
}

/**
* @brief CReaperTrack::CReaperTrack Construct a Reaper RPP "<TRACK>" for a given list of track items
* @param name the track name
* @param iid the sequential track id
* @param items the list of items in the track
*/
CReaperTrack::CReaperTrack(QString name, qint32& iid, QList<STrackItem> items)
{
QTextStream sOut(&out);

sOut << " <TRACK " << trackId.toString() << endl;
sOut << " NAME " << name << endl;
sOut << " TRACKID " << trackId.toString() << endl;

int ino = 1;
foreach (auto item, items) {
sOut << CReaperItem(name + " (" + QString::number(ino) + ")", item, iid).toString() << endl;
ino++;
iid++;
}
sOut << " >";

sOut.flush();
}

/**
* @brief CReaperProject::CReaperProject Construct a Reaper RPP "<REAPER_PROJECT>" for a given list of tracks
* @param tracks the list of tracks
*/
CReaperProject::CReaperProject(QMap<QString, QList<STrackItem>> tracks)
{
QTextStream sOut(&out);

sOut << "<REAPER_PROJECT 0.1 \"5.0\" 1551567848" << endl;
sOut << " RECORD_PATH \"\" \"\"" << endl;
sOut << " SAMPLERATE 48000 0 0" << endl;
sOut << " TEMPO 120 4 4" << endl;

qint32 iid = 0;
foreach(auto trackName, tracks.keys())
{
sOut << CReaperTrack(trackName, iid, tracks[trackName]).toString() << endl;
}

sOut << ">";

sOut.flush();
}
Loading

0 comments on commit 8d6cfd8

Please sign in to comment.