Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/audiomixerboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,8 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
// get all channels which are in use/not in use.
// We use the array index of vecChanInfo if the fader is in use,
// else INVALID_INDEX to specify it is not in use
// so must use "int" for the array type.
// so the array type is "int", which also keeps the comparisons below
// free of signedness warnings.

@pljones pljones Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a pretty strange way of putting it.

else INVALID_INDEX to specify it is not in use.
As INVALID_INDEX is of type int, an int type must also be
used here to avoid signedness warnings elsewhere.

int iFaderNumber[MAX_NUM_CHANNELS];

for ( size_t iChanID = 0; iChanID < MAX_NUM_CHANNELS; iChanID++ )
Expand Down
8 changes: 4 additions & 4 deletions src/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData, int iInSize )
return false;
}

// to get the number of input blocks we assume that the number of bytes for
// the sequence number is much smaller than the number of coded audio bytes
// to get the number of input blocks we assume that the total sequence number
// overhead, iNumBlocks * iNumBytesSeqNum, is smaller than iBlockSize
const int iNumBlocks = /* floor */ ( iInSize / iBlockSize );

// copy new data in internal buffer
Expand All @@ -191,8 +191,8 @@ bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData, int iInSize )
}

// The 1-byte sequence number wraps around at a count of 256. So, if a packet is delayed
// further than this we cannot detect it. But it does not matter since such a packet is
// more than 100 ms delayed so we have a bad network situation anyway. Therefore we
// further than half of this we cannot detect it. But it does not matter since such a packet is
// more than 170 ms delayed so we have a bad network situation anyway. Therefore we

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I find the whole comment (not this changed bit) very hard to digest with lots of repeated phrases.

we always move our "buffer window"
since we adjust the window
we move the "buffer window"

// assume that the sequence number difference between the received and local counter is
// correct. The idea of the following code is that we always move our "buffer window" so
// that the received packet fits into the buffer. By doing this we are robust against
Expand Down
6 changes: 3 additions & 3 deletions src/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,9 +716,9 @@ int CChannel::GetUploadRateKbps()
{
const int iAudioSizeOut = iNetwFrameSizeFact * iAudioFrameSizeSamples;

// we assume that the UDP packet which is transported via IP has an
// additional header size of ("Network Music Performance (NMP) in narrow
// band networks; Carot, Kraemer, Schuller; 2006")
// we assume the PPPoE-over-ATM DSL access path described in ("Network Music
// Performance (NMP) in narrow band networks; Carot, Kraemer, Schuller; 2006"),
// whose additional header size is

@pljones pljones Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment now omits the first line (UDP) from the description. It's probably also worth stating something like "PPPoE-over-ATM DSL chosen as a general domestic use case" (or whatever reason the authors gave in their paper).

// 8 (UDP) + 20 (IP without optional fields) = 28 bytes
// 2 (PPP) + 6 (PPPoE) + 18 (MAC) = 26 bytes
// 5 (RFC1483B) + 8 (AAL) + 10 (ATM) = 23 bytes
Expand Down
6 changes: 3 additions & 3 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ void CClient::SetDoAutoSockBufSize ( const bool bValue )
//
// When the first gain or pan change message is requested after an idle period (i.e. the timer is not
// running), it will be sent immediately, and a timer started. The timer period is dependent on
// the current ping time to the remote server.
// the current ping time to the remote server, which only a GUI client measures (see #3874).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not worth mentioning. Any "bad design" should be captured in an issue and addressed that way, rather than in code comments.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall AI hasn't done great on this "update the comments" exercise, but I think this change is valuable. Since the day robots took my writing career, I miss this eternal tension between developers and documentarians. The perfect should not be the enemy of the good. Futureware doesn't help anyone today. Should this matter become fixed, one could revel and delight in the removal of this mention of the fixed flaw. I've linked arms with developers and spun with delight as we threw out obsolete guidance. This worked well so long as I was the benevolent dictator of the documentation. Once the world moved to repos and toward engineers applying their engineering acumen to editorial judgements, as you do here, quality has suffered. Perfected futureware is the psychological bias of the lead engineer. Why mention a thing we should fix? To avoid suffering, that's why. My career involved using a magnifying lense on things developers want to disappear, and sometimes even hide. So this is nothing new. But please consider my differing point of view, oh benevolent dictator.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this matter become fixed, one could revel and delight in the removal of this mention of the fixed flaw.

No, it'll get overlooked. Probably even by an AI coding agent.

Headless client: the gain/pan rate limiter never adapts to ping time, and branches on an uninitialised value

It's not clear from the title of the referenced PR that it's directly related. And any "This is wrong" should have a "Fix in" reference rather than a "discovered as wrong in" reference. Again, it's negativity.

//
// If a gain or pan change message is requested while the timer is still running, the new value is not sent,
// but just stored in newGain or newPan within clientChannels[iId], and the minGainOrPanId and maxGainOrPanId
Expand Down Expand Up @@ -1000,7 +1000,7 @@ void CClient::OnControllerInMuteMyself ( bool bMute )
void CClient::OnClientIDReceived ( int iServerChanID )
{
// if we have just connected to a running server, iActiveChannels will be 0
// if iActiveChannels is not 0, the server must have been restarted on the fly
// if iActiveChannels is not 0, the server was restarted or our channel timed out
// in that case, channels might have changed, so clear our list to get it afresh.
if ( iActiveChannels != 0 )
{
Expand All @@ -1009,7 +1009,7 @@ void CClient::OnClientIDReceived ( int iServerChanID )
}

// allocate and map client-side channel 0
int iChanID = FindClientChannel ( iServerChanID, true ); // should always return channel 0
int iChanID = FindClientChannel ( iServerChanID, true ); // returns channel 0 for an in-range iServerChanID

// for headless mode we support to mute our own signal in the personal mix
// (note that the check for headless is done in the main.cpp and must not
Expand Down
1 change: 0 additions & 1 deletion src/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ class CClient : public QObject
void SetSettings ( CClientSettings* settings );

protected:
// Signal handler must be declared before pSettings for correct init order
CSignalHandler* pSignalHandler;
// Pointer to settings for MIDI and other config
CClientSettings* pSettings;
Expand Down
4 changes: 2 additions & 2 deletions src/clientdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,8 +575,8 @@ CClientDlg::CClientDlg ( CClient* pNCliP,

QObject::connect ( &ConnectDlg, &CConnectDlg::ReqServerListQuery, this, &CClientDlg::OnReqServerListQuery );

// note that this connection must be a queued connection, otherwise the server list ping
// times are not accurate and the client list may not be retrieved for all servers listed
// note that this delivery must be queued, otherwise the server list ping times are not
// accurate and the client list may not be retrieved for all servers listed

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. That's not what Qt::QueuedConnection means. The explanation should indicate something about the effect within the Qt signal/slot framework of the parameter and then why it's needed within the Jamulus architecture here.

// (it seems the sendto() function needs to be called from different threads to fire the
// packet immediately and do not collect packets before transmitting)
QObject::connect ( &ConnectDlg, &CConnectDlg::CreateCLServerListPingMes, this, &CClientDlg::OnCreateCLServerListPingMes, Qt::QueuedConnection );
Expand Down
3 changes: 1 addition & 2 deletions src/connectdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ CConnectDlg::CConnectDlg ( CClient* pNCliP, CClientSettings* pNSetP, const bool
cbxServerAddr->installEventFilter ( this );
lvwServers->installEventFilter ( this );

// set up list view for connected clients (note that the last column size
// must not be specified since this column takes all the remaining space)
// set up list view for connected clients
#ifdef ANDROID
// for Android we need larger numbers because of the default font size
lvwServers->setColumnWidth ( LVC_NAME, 200 );
Expand Down
2 changes: 1 addition & 1 deletion src/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ LED bar: lbr

// System block size, this is the block size on which the audio coder works.
// All other block sizes must be a multiple of this size.
// Note that the UpdateAutoSetting() function assumes a value of 128.
// Note that the IIR_WEIGTH_* filter constants in buffer.h assume values of 64 and 128.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly worth splitting out "completely wrong" from "unclear or unhelpful". This looks like the former.

#define SYSTEM_FRAME_SIZE_SAMPLES 64
#define DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ( 2 * SYSTEM_FRAME_SIZE_SAMPLES )

Expand Down
4 changes: 2 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,8 +706,8 @@ int main ( int argc, char** argv )
#ifndef HEADLESS
if ( bUseGUI )
{
// by definition, when running with the GUI we always default to registering somewhere but
// until the settings are loaded we do not know where, so we cannot be prescriptive here
// when running with the GUI, until the settings are loaded we do not know whether or
// where this server will register, so we cannot be prescriptive here

if ( !strServerListFileName.isEmpty() )
{
Expand Down
2 changes: 1 addition & 1 deletion src/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ class CProtocol : public QObject
int iOldRecID;
int iOldRecCnt;

// these two objects must be sequred by a mutex
// these two objects must be secured by a mutex
uint8_t iCounter;
std::list<CSendMessage> SendMessQueue;

Expand Down
4 changes: 2 additions & 2 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ CServer::CServer ( const int iNewMaxNumChan,
iServerFrameSizeSamples = SYSTEM_FRAME_SIZE_SAMPLES;
}

// To avoid audio clitches, in the entire realtime timer audio processing
// To avoid audio glitches, in the entire realtime timer audio processing
// routine including the ProcessData no memory must be allocated. Since we
// do not know the required sizes for the vectors, we allocate memory for
// the worst case here:
Expand Down Expand Up @@ -662,7 +662,7 @@ void CServer::OnTimer()
bool bUseMT = false;
int iNumBlocks = 0; // init number of blocks for multithreading
int iMTBlockSize = 0; // init block size for multithreading
bChannelIsNowDisconnected = false; // note that the flag must be a member function since QtConcurrent::run can only take 5 params
bChannelIsNowDisconnected = false; // note that the flag is a member since DecodeReceiveData sets it and the check below reads it

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. Seems a pretty useless comment now. "This is a flag. It's read and written." The earlier comment explained why it existed at all.


{
// Make put and get calls thread safe.
Expand Down
2 changes: 1 addition & 1 deletion src/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ void CSocket::Init ( const quint16 iNewPortNumber,
UdpSocket4 = socket ( AF_INET, SOCK_DGRAM, 0 );
if ( UdpSocket4 == INVALID_SOCKET )
{
// IPv4 requested but not available, throw error (should never happen, but check anyway)
// socket creation can fail (e.g. under file descriptor exhaustion), throw error
throw CGenErr ( "IPv4 requested but not available on this system.", "Network Error" );
}

Expand Down
6 changes: 3 additions & 3 deletions src/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ class CSocket : public QObject
void ProtocolCLMessageReceived ( int iRecID, CVector<uint8_t> vecbyMesBodyData, CHostAddress HostAdr );
};

/* Socket which runs in a separate high priority thread --------------------- */
/* Socket which runs in a separate thread requesting high priority ---------- */
// The receive socket should be put in a high priority thread to ensure the GUI
// does not effect the stability of the audio stream (e.g. if the GUI is on
// does not affect the stability of the audio stream (e.g. if the GUI is on
// high load because of a table update, the incoming network packets must still
// be put in the jitter buffer with highest priority).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(non-feedback)
It's really the GUI that needs its own thread. The main Jamulus Client should all run at real time scheduling / raised priority: audio, client and network. That part of the code needs to be kept "lean and mean" in terms of performance...

(I'll continue rumbling about this...)

class CHighPrioSocket : public QObject
Expand Down Expand Up @@ -240,7 +240,7 @@ class CHighPrioSocket : public QObject

void Init()
{
// Creation of the new socket thread which has to have the highest
// Creation of the new socket thread which requests the highest
// possible thread priority to make sure the jitter buffer is reliably
// filled with the network audio packets and does not get interrupted
// by other GUI threads. The following code is based on:
Expand Down
Loading