Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve UX in error messages (#1568) #1732

Merged
merged 14 commits into from
Jun 21, 2021
43 changes: 21 additions & 22 deletions linux/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,15 @@ void CSound::OpenJack ( const bool bNoAutoJackConnect, const char* jackClientNam
serverName = "default";
}
qInfo() << qUtf8Printable (
QString ( "Connecting to jack \"%1\" instance (use the JACK_DEFAULT_SERVER environment variable to change this)." ).arg ( serverName ) );
QString ( "Connecting to JACK \"%1\" instance (use the JACK_DEFAULT_SERVER environment variable to change this)." ).arg ( serverName ) );
ann0see marked this conversation as resolved.
Show resolved Hide resolved

// try to become a client of the JACK server
pJackClient = jack_client_open ( jackClientName, JackNullOption, &JackStatus );

if ( pJackClient == nullptr )
{
throw CGenErr ( tr ( "The Jack server is not running. This software "
"requires a Jack server to run. Normally if the Jack server is "
"not running this software will automatically start the Jack server. "
"It seems that this auto start has not worked. Try to start the Jack "
"server manually." ) );
throw CGenErr ( tr ( "JACK couldn't be started automatically. "
"Please start JACK manually and check for error messages." ) );
}

// tell the JACK server to call "process()" whenever
Expand All @@ -64,16 +61,10 @@ void CSound::OpenJack ( const bool bNoAutoJackConnect, const char* jackClientNam
// check sample rate, if not correct, just fire error
if ( jack_get_sample_rate ( pJackClient ) != SYSTEM_SAMPLE_RATE_HZ )
{
throw CGenErr ( tr ( "The Jack server sample rate is different from "
"the required one. The required sample rate is:" ) +
" <b>" + QString().setNum ( SYSTEM_SAMPLE_RATE_HZ ) + " Hz</b>. " +
tr ( "You can "
"use a tool like <i><a href=\"https://qjackctl.sourceforge.io\">QJackCtl</a></i> "
"to adjust the Jack server sample rate." ) +
"<br>" +
tr ( "Make sure to set the "
"Frames/Period to a low value like " ) +
QString().setNum ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ) + tr ( " to achieve a low delay." ) );
throw CGenErr ( QString ( tr ( "JACK isn't running at a sample rate of <b>%1 Hz</b>. Please use "
"a tool like <i><a href=\"https://qjackctl.sourceforge.io\">QjackCtl</a></i> to set the "
"the JACK sample rate to %1 Hz." ) )
.arg ( SYSTEM_SAMPLE_RATE_HZ ) );
}

// create four ports (two for input, two for output -> stereo)
Expand All @@ -87,7 +78,10 @@ void CSound::OpenJack ( const bool bNoAutoJackConnect, const char* jackClientNam

if ( ( input_port_left == nullptr ) || ( input_port_right == nullptr ) || ( output_port_left == nullptr ) || ( output_port_right == nullptr ) )
{
throw CGenErr ( tr ( "The Jack port registering failed." ) );
throw CGenErr ( QString ( tr ( "The JACK port registration failed. This is probably an error with JACK. Please stop %1 and JACK. "
"Afterwards check if another program at a sample rate of %2 Hz can connect to JACK." ) )
.arg ( APP_NAME )
.arg ( SYSTEM_SAMPLE_RATE_HZ ) );
}

// optional MIDI initialization
Expand All @@ -97,7 +91,9 @@ void CSound::OpenJack ( const bool bNoAutoJackConnect, const char* jackClientNam

if ( input_port_midi == nullptr )
{
throw CGenErr ( tr ( "The Jack port registering failed." ) );
throw CGenErr ( QString ( tr ( "The JACK port registration failed. This is probably an error with JACK. Please stop %1 and JACK. "
"Afterwards, check if another MIDI program can connect to JACK." ) )
.arg ( APP_NAME ) );
}
}
else
Expand All @@ -108,7 +104,8 @@ void CSound::OpenJack ( const bool bNoAutoJackConnect, const char* jackClientNam
// tell the JACK server that we are ready to roll
if ( jack_activate ( pJackClient ) )
{
throw CGenErr ( tr ( "Cannot activate the Jack client." ) );
throw CGenErr ( QString ( tr ( "Can't activate the JACK client. This is probably an error with JACK. Please check the JACK output." ) )
.arg ( APP_NAME ) );
}

if ( !bNoAutoJackConnect )
Expand Down Expand Up @@ -210,9 +207,11 @@ int CSound::Init ( const int /* iNewPrefMonoBufferSize */ )
// without a Jack server, Jamulus makes no sense to run, throw an error message
if ( bJackWasShutDown )
{
throw CGenErr ( tr ( "The Jack server was shut down. This software "
"requires a Jack server to run. Try to restart the software to "
"solve the issue." ) );
throw CGenErr ( QString ( tr ( "JACK was shut down. %1 "
"requires JACK to run. Please restart %1 to "
"start JACK again. "
"the JACK output." ) )
.arg ( APP_NAME ) );
}

// get actual buffer size
Expand Down
42 changes: 21 additions & 21 deletions mac/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,17 @@ void CSound::GetAvailableInOutDevices()

if ( AudioObjectGetPropertyData ( kAudioObjectSystemObject, &stPropertyAddress, 0, NULL, &iPropertySize, &audioInputDevice[lNumDevs] ) )
{
throw CGenErr ( tr ( "CoreAudio input AudioHardwareGetProperty call failed. "
"It seems that no sound card is available in the system." ) );
throw CGenErr ( tr ( "No sound card is available in your system. "
ann0see marked this conversation as resolved.
Show resolved Hide resolved
"CoreAudio input AudioHardwareGetProperty call failed." ) );
}

iPropertySize = sizeof ( AudioDeviceID );
stPropertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;

if ( AudioObjectGetPropertyData ( kAudioObjectSystemObject, &stPropertyAddress, 0, NULL, &iPropertySize, &audioOutputDevice[lNumDevs] ) )
{
throw CGenErr ( tr ( "CoreAudio output AudioHardwareGetProperty call failed. "
"It seems that no sound card is available in the system." ) );
throw CGenErr ( tr ( "No sound card is available in the system. "
ann0see marked this conversation as resolved.
Show resolved Hide resolved
"CoreAudio output AudioHardwareGetProperty call failed." ) );
}

lNumDevs++; // next device
Expand Down Expand Up @@ -281,7 +281,7 @@ QString CSound::LoadAndInitializeDriver ( QString strDriverName, bool )
// if the selected driver was not found, return an error message
if ( iDriverIdx == INVALID_INDEX )
{
return tr ( "The current selected audio device is no longer present in the system." );
return tr ( "The currently selected audio device is no longer present. Please check your audio device." );
ann0see marked this conversation as resolved.
Show resolved Hide resolved
}

// check device capabilities if it fulfills our requirements
Expand Down Expand Up @@ -382,7 +382,7 @@ QString CSound::CheckDeviceCapabilities ( const int iDriverIdx )

if ( AudioObjectGetPropertyData ( audioInputDevice[iDriverIdx], &stPropertyAddress, 0, NULL, &iPropertySize, &inputSampleRate ) )
{
return QString ( tr ( "The audio input device is no longer available." ) );
return QString ( tr ( "The audio input device is no longer available. Please check if your input device is connected correctly." ) );
}

if ( inputSampleRate != fSystemSampleRate )
Expand All @@ -391,10 +391,9 @@ QString CSound::CheckDeviceCapabilities ( const int iDriverIdx )
if ( AudioObjectSetPropertyData ( audioInputDevice[iDriverIdx], &stPropertyAddress, 0, NULL, sizeof ( Float64 ), &fSystemSampleRate ) !=
noErr )
{
return QString ( tr ( "Current system audio input device sample "
"rate of %1 Hz is not supported. Please open the Audio-MIDI-Setup in "
"Applications->Utilities and try to set a sample rate of %2 Hz." ) )
.arg ( static_cast<int> ( inputSampleRate ) )
return QString ( tr ( "The sample rate on the current input device isn't %1 Hz and is therefore incompatible. "
"Please select another device or try setting the sample rate to %1 Hz "
"manually via Audio-MIDI-Setup (in Applications->Utilities)." ) )
.arg ( SYSTEM_SAMPLE_RATE_HZ );
}
}
Expand All @@ -404,7 +403,7 @@ QString CSound::CheckDeviceCapabilities ( const int iDriverIdx )

if ( AudioObjectGetPropertyData ( audioOutputDevice[iDriverIdx], &stPropertyAddress, 0, NULL, &iPropertySize, &outputSampleRate ) )
{
return QString ( tr ( "The audio output device is no longer available." ) );
return QString ( tr ( "The audio output device is no longer available. Please check if your output device is connected correctly." ) );
}

if ( outputSampleRate != fSystemSampleRate )
Expand All @@ -413,10 +412,9 @@ QString CSound::CheckDeviceCapabilities ( const int iDriverIdx )
if ( AudioObjectSetPropertyData ( audioOutputDevice[iDriverIdx], &stPropertyAddress, 0, NULL, sizeof ( Float64 ), &fSystemSampleRate ) !=
noErr )
{
return QString ( tr ( "Current system audio output device sample "
"rate of %1 Hz is not supported. Please open the Audio-MIDI-Setup in "
"Applications->Utilities and try to set a sample rate of %2 Hz." ) )
.arg ( static_cast<int> ( outputSampleRate ) )
return QString ( tr ( "The sample rate on the current output device isn't %1 Hz and is therefore incompatible. "
"Please select another device or try setting the sample rate to %1 Hz "
"manually via Audio-MIDI-Setup (in Applications->Utilities)." ) )
.arg ( SYSTEM_SAMPLE_RATE_HZ );
}
}
Expand Down Expand Up @@ -462,8 +460,9 @@ QString CSound::CheckDeviceCapabilities ( const int iDriverIdx )
( CurDevStreamFormat.mBitsPerChannel != 32 ) || ( !( CurDevStreamFormat.mFormatFlags & kAudioFormatFlagIsFloat ) ) ||
( !( CurDevStreamFormat.mFormatFlags & kAudioFormatFlagIsPacked ) ) )
{
return tr ( "The audio input stream format for this audio device is "
"not compatible with this software." );
return QString ( tr ( "The stream format on the current input device isn't "
"compatible with this software. Please select another device." ) )
.arg ( APP_NAME );
}

// check the output
Expand All @@ -473,8 +472,9 @@ QString CSound::CheckDeviceCapabilities ( const int iDriverIdx )
( CurDevStreamFormat.mBitsPerChannel != 32 ) || ( !( CurDevStreamFormat.mFormatFlags & kAudioFormatFlagIsFloat ) ) ||
( !( CurDevStreamFormat.mFormatFlags & kAudioFormatFlagIsPacked ) ) )
{
return tr ( "The audio output stream format for this audio device is "
"not compatible with this software." );
return QString ( tr ( "The stream format on the current output device isn't "
"compatible with %1. Please select another device." ) )
.arg ( APP_NAME );
}

// store the input and out number of channels for this device
Expand Down Expand Up @@ -726,8 +726,8 @@ int CSound::Init ( const int iNewPrefMonoBufferSize )
// Error message string: in case buffer sizes on input and output cannot be
// set to the same value
const QString strErrBufSize = tr ( "The buffer sizes of the current "
"input and output audio device cannot be set to a common value. Please "
"choose other input/output audio devices in your system settings." );
"input and output audio device can't be set to a common value. Please "
"select different input/output devices in your system settings." );

// try to set input buffer size
iActualMonoBufferSize = SetBufferSize ( audioInputDevice[lCurDev], true, iNewPrefMonoBufferSize );
Expand Down
22 changes: 8 additions & 14 deletions src/soundbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ QString CSoundBase::SetDev ( const QString strDevName )
LoadAndInitializeDriver ( strCurDevName, false );

// store error return message
strReturn = QString ( tr ( "The selected audio device could not be used "
strReturn = QString ( tr ( "Can't use the selected audio device "
"because of the following error: " ) ) +
strErrorMessage + QString ( tr ( " The previous driver will be selected." ) );
}
Expand Down Expand Up @@ -154,10 +154,9 @@ QString CSoundBase::SetDev ( const QString strDevName )
if ( !strDevName.isEmpty() )
{
strReturn = tr ( "The previously selected audio device "
"is no longer available or the audio driver properties have changed to a state which "
"is incompatible with this software. We now try to find a valid audio device. This new "
"audio device might cause audio feedback. So, before connecting to a server, please "
"check the audio device setting." );
"is no longer available or the driver has changed to an incompatible state."
"We'll attempt to find a valid audio device, but this new audio device may cause feedback."
"Before connecting to a server, please check your audio device settings." );
}

// try to load and initialize any valid driver
Expand All @@ -166,13 +165,8 @@ QString CSoundBase::SetDev ( const QString strDevName )
if ( !vsErrorList.isEmpty() )
{
// create error message with all details
QString sErrorMessage = "<b>" + tr ( "No usable " ) + strSystemDriverTechniqueName +
tr ( " audio device "
"(driver) found." ) +
"</b><br><br>" +
tr ( "In the following there is a list of all available drivers "
"with the associated error message:" ) +
"<ul>";
QString sErrorMessage = "<b>" + QString ( tr ( "No usable %1 audio device found." ) ).arg ( strSystemDriverTechniqueName ) +
"</b><br><br>" + tr ( "These are all the available drivers with error messages:" ) + "<ul>";

for ( int i = 0; i < lNumDevs; i++ )
{
Expand All @@ -184,14 +178,14 @@ QString CSoundBase::SetDev ( const QString strDevName )
// to be able to access the ASIO driver setup for changing, e.g., the sample rate, we
// offer the user under Windows that we open the driver setups of all registered
// ASIO drivers
sErrorMessage = sErrorMessage + "<br/>" + tr ( "Do you want to open the ASIO driver setups?" );
sErrorMessage += "<br/>" + tr ( "Do you want to open the ASIO driver setup to try changing your configuration to a working state?" );

if ( QMessageBox::Yes == QMessageBox::information ( nullptr, APP_NAME, sErrorMessage, QMessageBox::Yes | QMessageBox::No ) )
{
LoadAndInitializeFirstValidDriver ( true );
ann0see marked this conversation as resolved.
Show resolved Hide resolved
}

sErrorMessage = APP_NAME + tr ( " could not be started because of audio interface issues." );
sErrorMessage = QString ( tr ( "Can't start %1. Please restart %1 and check/reconfigure your audio settings." ) ).arg ( APP_NAME );
#endif

throw CGenErr ( sErrorMessage );
Expand Down
Loading