Skip to content

Commit

Permalink
Warn on audio device failure rather than abort.
Browse files Browse the repository at this point in the history
In some cases, being able to hear the signal is not important, and a
system has no usable audio device. This patch removes the error dialog
and exit when no device is found. Instead, "NO AUDIO" is added to the
title. Note that the PortAudio case may still need some work. Only
PulseAudio has been tested.

Signed-off-by: Jeff Long <willcode4@gmail.com>
  • Loading branch information
willcode committed Jun 11, 2024
1 parent 4c825c1 commit b0a8d1d
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 66 deletions.
35 changes: 0 additions & 35 deletions src/applications/gqrx/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,41 +98,6 @@ int main(int argc, char *argv[])
return 0;
}

// check whether audio backend is functional
#ifdef WITH_PORTAUDIO
PaError err = Pa_Initialize();
if (err != paNoError)
{
QString message = QString("Portaudio error: %1").arg(Pa_GetErrorText(err));
qCritical() << message;
QMessageBox::critical(nullptr, "Audio Error", message,
QMessageBox::Abort, QMessageBox::NoButton);
return 1;
}
#endif

#ifdef WITH_PULSEAUDIO
int error = 0;
pa_simple *test_sink;
pa_sample_spec ss;

ss.format = PA_SAMPLE_FLOAT32LE;
ss.rate = 48000;
ss.channels = 2;
test_sink = pa_simple_new(NULL, "Gqrx Test", PA_STREAM_PLAYBACK, NULL,
"Test stream", &ss, NULL, NULL, &error);
if (!test_sink)
{
QString message = QString("Pulseaudio error: %1").arg(pa_strerror(error));
qCritical() << message;
QMessageBox::critical(0, "Audio Error", message,
QMessageBox::Abort, QMessageBox::NoButton);
return 1;
}
pa_simple_free(test_sink);
#endif


if (parser.isSet("conf"))
{
cfg_file = parser.value("conf");
Expand Down
3 changes: 2 additions & 1 deletion src/applications/gqrx/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,8 @@ bool MainWindow::loadConfig(const QString& cfgfile, bool check_crash,
}

// Update window title
setWindowTitle(QString("Gqrx %1 - %2").arg(VERSION).arg(indev));
const char* audio_status = rx->has_audio_device() ? "" : " - NO AUDIO";
setWindowTitle(QString("Gqrx %1 - %2%3").arg(VERSION).arg(indev).arg(audio_status));

// Add available antenna connectors to the UI
std::vector<std::string> antennas = rx->get_antennas();
Expand Down
43 changes: 22 additions & 21 deletions src/applications/gqrx/receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ receiver::receiver(const std::string input_device,
d_iq_rev(false),
d_dc_cancel(false),
d_iq_balance(false),
d_demod(RX_DEMOD_OFF)
d_demod(RX_DEMOD_OFF),
d_has_audio_device(false)
{

tb = gr::make_top_block("gqrx");
Expand Down Expand Up @@ -125,13 +126,20 @@ receiver::receiver(const std::string input_device,

audio_udp_sink = make_udp_sink_f();

try {
#ifdef WITH_PULSEAUDIO
audio_snk = make_pa_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
audio_snk = make_pa_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
#elif WITH_PORTAUDIO
audio_snk = make_portaudio_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
audio_snk = make_portaudio_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
#else
audio_snk = gr::audio::sink::make(d_audio_rate, audio_device, true);
audio_snk = gr::audio::sink::make(d_audio_rate, audio_device, true);
#endif
d_has_audio_device = true;
}
// No audio device a null sink.
catch (const std::exception& error) {
audio_snk = gr::blocks::null_sink::make(sizeof(float));
}

output_devstr = audio_device;

Expand All @@ -142,10 +150,6 @@ receiver::receiver(const std::string input_device,
/* sniffer_rr is created at each activation. */

set_demod(RX_DEMOD_NFM);

gr::prefs pref;
qDebug() << "Using audio backend:"
<< pref.get_string("audio", "audio_module", "N/A").c_str();
}

receiver::~receiver()
Expand Down Expand Up @@ -284,20 +288,17 @@ void receiver::set_output_device(const std::string device)
#else
audio_snk = gr::audio::sink::make(d_audio_rate, device, true);
#endif

if (d_demod != RX_DEMOD_OFF)
{
tb->connect(audio_gain0, 0, audio_snk, 0);
tb->connect(audio_gain1, 0, audio_snk, 1);
}

tb->unlock();

} catch (std::exception &x) {
tb->unlock();
// handle problems on non-freeing devices
throw x;
}
catch (const std::exception& error) {
audio_snk = gr::blocks::null_sink::make(sizeof(float));
}
if (d_demod != RX_DEMOD_OFF)
{
tb->connect(audio_gain0, 0, audio_snk, 0);
tb->connect(audio_gain1, 0, audio_snk, 1);
}

tb->unlock();
}

/** Get a list of available antenna connectors. */
Expand Down
11 changes: 4 additions & 7 deletions src/applications/gqrx/receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ class receiver
status start_udp_streaming(const std::string host, int port, bool stereo);
status stop_udp_streaming();

bool has_audio_device(void) { return d_has_audio_device; }

/* I/Q recording and playback */
status start_iq_recording(const std::string filename);
status stop_iq_recording();
Expand Down Expand Up @@ -285,13 +287,8 @@ class receiver
sniffer_f_sptr sniffer; /*!< Sample sniffer for data decoders. */
resampler_ff_sptr sniffer_rr; /*!< Sniffer resampler. */

#ifdef WITH_PULSEAUDIO
pa_sink_sptr audio_snk; /*!< Pulse audio sink. */
#elif WITH_PORTAUDIO
portaudio_sink_sptr audio_snk; /*!< portaudio sink */
#else
gr::audio::sink::sptr audio_snk; /*!< gr audio sink */
#endif
bool d_has_audio_device;
gr::basic_block_sptr audio_snk; /*!< Audio sink (pulse, portaudio, gr-audio). */

//! Get a path to a file containing random bytes
static std::string get_zero_file(void);
Expand Down
3 changes: 1 addition & 2 deletions src/pulseaudio/pa_sink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ pa_sink::pa_sink(const string device_name, int audio_rate,
&error);

if (!d_pasink) {
/** FIXME: Throw an exception **/
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
throw std::runtime_error("Unable to open pulseaudio device.");
}

}
Expand Down

0 comments on commit b0a8d1d

Please sign in to comment.