mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-25 21:58:38 -05:00
More flexible execution of the user's hardware controller
Updated ways to implement a user defined hardware controller which is executed just after band changes during WSPR band hopping operation. Allows the user_hardware executable to be located in any directory on the PATH environment variable. On Windows any file extension listed on the PATHEXT environment variable may be used, the first match using PATH and PATHEXT will be executed. On Windows this is achieved by using CMD.EXE with a '/C' command line flag, i.e. the user's hardware controller is executed like this: CMD.EXE /C user_hardware nn where 'nn' is the new band as an integer in meters. On non-Windows systems the user's executable will be run if it is found on the directories specified by the PATH environment variable, and it is executable, i.e. it is equivalent to something like: /bin/sh -c user_hardware nn where 'nn' is the new band as an integer in meters. In all cases the user_hardware controller should exit with a zero status, otherwise it have been deemed to have failed. On Windows avoid an exit status of one as that is utilized by CMD.EXE to indicate the file was not found, which WSJT-X ignores silently. This change means the prior need to put the user's hardware controller into a WSJT-X installation directory like /usr/local/bin or C:\WSJT\wsjtx\bin is no longer necessary.
This commit is contained in:
parent
a24f402655
commit
27b4f2939a
@ -662,7 +662,12 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
#endif
|
||||
connect(&proc_jt9, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
|
||||
[this] (int exitCode, QProcess::ExitStatus status) {
|
||||
subProcessFailed (&proc_jt9, exitCode, status);
|
||||
if (subProcessFailed (&proc_jt9, exitCode, status))
|
||||
{
|
||||
m_valid = false; // ensures exit if still
|
||||
// constructing
|
||||
QTimer::singleShot (0, this, SLOT (close ()));
|
||||
}
|
||||
});
|
||||
connect(&p1, &QProcess::started, [this] () {
|
||||
showStatusMessage (QString {"Started: %1 \"%2\""}.arg (p1.program ()).arg (p1.arguments ().join (QLatin1String {"\" \""})));
|
||||
@ -680,25 +685,42 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
#endif
|
||||
connect(&p1, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
|
||||
[this] (int exitCode, QProcess::ExitStatus status) {
|
||||
subProcessFailed (&p1, exitCode, status);
|
||||
if (subProcessFailed (&p1, exitCode, status))
|
||||
{
|
||||
m_valid = false; // ensures exit if still
|
||||
// constructing
|
||||
QTimer::singleShot (0, this, SLOT (close ()));
|
||||
}
|
||||
});
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK (5, 6, 0)
|
||||
connect(&p3, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
|
||||
[this] (QProcess::ProcessError error) {
|
||||
subProcessError (&p3, error);
|
||||
});
|
||||
#else
|
||||
connect(&p3, &QProcess::errorOccurred, [this] (QProcess::ProcessError error) {
|
||||
subProcessError (&p3, error);
|
||||
});
|
||||
#endif
|
||||
#if not defined(Q_OS_WIN)
|
||||
if (QProcess::FailedToStart != error)
|
||||
#endif
|
||||
{
|
||||
subProcessError (&p3, error);
|
||||
}
|
||||
});
|
||||
connect(&p3, &QProcess::started, [this] () {
|
||||
showStatusMessage (QString {"Started: %1 \"%2\""}.arg (p3.program ()).arg (p3.arguments ().join (QLatin1String {"\" \""})));
|
||||
});
|
||||
connect(&p3, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
|
||||
[this] (int exitCode, QProcess::ExitStatus status) {
|
||||
subProcessFailed (&p3, exitCode, status);
|
||||
#if defined(Q_OS_WIN)
|
||||
// We forgo detecting user_hardware failures with exit
|
||||
// code 1 on Windows. This is because we use CMD.EXE to
|
||||
// run the executable. CMD.EXE returns exit code 1 when it
|
||||
// can't find the target executable.
|
||||
if (exitCode != 1) // CMD.EXE couldn't find file to execute
|
||||
#endif
|
||||
{
|
||||
subProcessFailed (&p3, exitCode, status);
|
||||
}
|
||||
});
|
||||
|
||||
// hook up save WAV file exit handling
|
||||
@ -2335,7 +2357,7 @@ void MainWindow::setup_status_bar (bool vhf)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::subProcessFailed (QProcess * process, int exit_code, QProcess::ExitStatus status)
|
||||
bool MainWindow::subProcessFailed (QProcess * process, int exit_code, QProcess::ExitStatus status)
|
||||
{
|
||||
if (m_valid && (exit_code || QProcess::NormalExit != status))
|
||||
{
|
||||
@ -2352,9 +2374,9 @@ void MainWindow::subProcessFailed (QProcess * process, int exit_code, QProcess::
|
||||
, tr ("Running: %1\n%2")
|
||||
.arg (process->program () + ' ' + arguments.join (' '))
|
||||
.arg (QString {process->readAllStandardError()}));
|
||||
QTimer::singleShot (0, this, SLOT (close ()));
|
||||
m_valid = false; // ensures exit if still constructing
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::subProcessError (QProcess * process, QProcess::ProcessError)
|
||||
@ -2372,8 +2394,8 @@ void MainWindow::subProcessError (QProcess * process, QProcess::ProcessError)
|
||||
, tr ("Running: %1\n%2")
|
||||
.arg (process->program () + ' ' + arguments.join (' '))
|
||||
.arg (process->errorString ()));
|
||||
QTimer::singleShot (0, this, SLOT (close ()));
|
||||
m_valid = false; // ensures exit if still constructing
|
||||
QTimer::singleShot (0, this, SLOT (close ()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7895,22 +7917,25 @@ void MainWindow::WSPR_scheduling ()
|
||||
if (hop_data.frequencies_index_ >= 0) { // new band
|
||||
ui->bandComboBox->setCurrentIndex (hop_data.frequencies_index_);
|
||||
on_bandComboBox_activated (hop_data.frequencies_index_);
|
||||
QStringList prefixes {".bat", ".cmd", ".exe", ""};
|
||||
QString target;
|
||||
for (auto const& prefix : prefixes)
|
||||
{
|
||||
target = QDir {m_appDir}.absoluteFilePath (QLatin1String {"user_hardware"});
|
||||
QFileInfo f {target + prefix};
|
||||
if (f.isExecutable ()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (target.size ())
|
||||
{
|
||||
// Execute user's hardware controller
|
||||
p3.start(QDir::toNativeSeparators (target)
|
||||
, QStringList {m_config.bands ()->find (m_freqNominal).remove ('m')});
|
||||
}
|
||||
// Execute user's hardware controller
|
||||
auto const& band = m_config.bands ()->find (m_freqNominal).remove ('m');
|
||||
#if defined(Q_OS_WIN)
|
||||
// On windows we use CMD.EXE to find and execute the
|
||||
// user_hardware executable. This means that the first matching
|
||||
// file extension on the PATHEXT environment variable found on
|
||||
// the PATH environment variable path list. This give maximum
|
||||
// flexibility for users to write user_hardware in their
|
||||
// language of choice, and place the file anywhere on the PATH
|
||||
// environment variable. Equivalent to typing user_hardware
|
||||
// without any path or extension at the CMD.EXE prompt.
|
||||
p3.start("CMD", QStringList {QLatin1String {"/C"}, QLatin1String {"user_hardware"}, band});
|
||||
#else
|
||||
// On non-Windows systems we expect the user_hardware executable
|
||||
// to be anywhere in the paths specified in the PATH environment
|
||||
// variable path list, and executable. Equivalent to typing
|
||||
// user_hardware without any path at the shell prompt.
|
||||
p3.start(QLatin1String {"user_hardware"}, QStringList {band});
|
||||
#endif
|
||||
|
||||
// Produce a short tuneup signal
|
||||
m_tuneup = false;
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QLabel>
|
||||
@ -749,7 +750,7 @@ private:
|
||||
void rm_tb4(QString houndCall);
|
||||
void read_wav_file (QString const& fname);
|
||||
void decodeDone ();
|
||||
void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
||||
bool subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
||||
void subProcessError (QProcess *, QProcess::ProcessError);
|
||||
void statusUpdate () const;
|
||||
void update_watchdog_label ();
|
||||
|
Loading…
Reference in New Issue
Block a user