From 4f4c535c4e02750e7c65b47cc7ba08a4728479f2 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 10 Aug 2013 15:29:55 +0000 Subject: [PATCH] Added audio channel support. Audio input can be mono, left of stereo pair or, right of stereo pair. Audio output can be mono, left of stereo pair, right of stereo pair or, both of stereo pair (the same output goes to both channels in both mode). Settings are remembered between sessions. Stream channel suport is implemented mainly in the new AudioDevice class which is now the base class of Modulator and Detector. Audio channels are selected on the configuration screen. Only supported channel configurations per device can be selected. Audio output volume (actually attenuation) is now possible from the GUI. I have added a slider control to the main window; I don't necessarily propose this as a final release location for the widget as I understand that changes to the main screen are sensitive. This location is just a starting suggestion for a trial. The volume (attenuation) setting is remembered between sessions and is not device dependent. This addresses all issues of volume setting on *nix versions since there is no need to use pavucontrol to set audio levels. The volume (attenuation) action is logarithmic. Shaped CW keying has been implemented in Modulator although it is currently disabled as I am not 100% happy wth the implementation. If you want to try it define the C++ preprocessor macro WSJT_SOFT_KEYING in your build. The Modulator instance has been moved to the same thread as the SoundOutput instance as it should have been since the output callback already operates in that thread. Cross thread slots are now correctly called in a thread safe way as a result. A number of files where in the SVN repository with DOS line endings which I have removed. SVN users on Windows need set the config for native line endings so that DOS line endings are automatically stripped on checkin. The DevSetup class now holds it's UI o the heap to reduce imapact on build dependencies. The application settings are now passed to objects from the main.cpp file. Management of settings are moved to the responsible classes (top level windows). This has involved a few settings moving groups so users will see some settings reverting to default values on the first run of an update. Persistance of top level windows geometry and position is now handled in the recommened manner (constructor for load, closeEvent for store in modal windows and, hideEvent for store in modeless dialogs). The MainWindow class now holds its children as members rather than global variables. The LogQSO class now hides its implementation and takes responsibility for its own settings and widows rendering parameters. A new settings file group is implemented to persist the LogQSO class settings. The WideGraph class now hides its implementation and manages its own settings and window rendering parameters. --This line, and those below, will be ignored-- M Modulator.cpp M rigclass.cpp M widegraph.cpp M signalmeter.cpp M soundin.cpp M soundout.cpp M mainwindow.h M main.cpp M meterwidget.h M devsetup.cpp M mainwindow.ui M Detector.cpp M logqso.h M rigclass.h M mainwindow.cpp M meterwidget.cpp M soundin.h M devsetup.ui M wsjtx.pro M devsetup.h M logqso.cpp M Modulator.hpp M psk_reporter.cpp M killbyname.cpp M Detector.hpp M signalmeter.h M widegraph.h M psk_reporter.h M soundout.h M PSKReporter.h M lib/afc65b.f90 M lib/gran.c M lib/usleep.c M lib/afc9.f90 M lib/wrapkarn.c A AudioDevice.hpp git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3542 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- AudioDevice.hpp | 105 ++++++++ Detector.cpp | 23 +- Detector.hpp | 28 +- Modulator.cpp | 118 ++++----- Modulator.hpp | 44 ++-- PSKReporter.h | 254 +++++++++--------- devsetup.cpp | 629 ++++++++++++++++++++++++-------------------- devsetup.h | 22 +- devsetup.ui | 213 +++++++++------ killbyname.cpp | 568 ++++++++++++++++++++-------------------- lib/afc65b.f90 | 118 ++++----- lib/afc9.f90 | 116 ++++----- lib/gran.c | 56 ++-- lib/usleep.c | 10 +- lib/wrapkarn.c | 140 +++++----- logqso.cpp | 371 +++++++++++++------------- logqso.h | 107 ++++---- main.cpp | 7 +- mainwindow.cpp | 536 +++++++++++++++++++------------------- mainwindow.h | 30 ++- mainwindow.ui | 97 ++++--- meterwidget.cpp | 102 ++++---- meterwidget.h | 60 ++--- psk_reporter.cpp | 224 ++++++++-------- psk_reporter.h | 84 +++--- rigclass.cpp | 664 +++++++++++++++++++++++------------------------ rigclass.h | 196 +++++++------- signalmeter.cpp | 106 ++++---- signalmeter.h | 64 ++--- soundin.cpp | 7 +- soundin.h | 2 +- soundout.cpp | 52 +++- soundout.h | 12 +- widegraph.cpp | 103 ++++---- widegraph.h | 181 ++++++------- wsjtx.pro | 2 +- 36 files changed, 2877 insertions(+), 2574 deletions(-) create mode 100644 AudioDevice.hpp diff --git a/AudioDevice.hpp b/AudioDevice.hpp new file mode 100644 index 000000000..2f4cfd313 --- /dev/null +++ b/AudioDevice.hpp @@ -0,0 +1,105 @@ +#ifndef AUDIODEVICE_HPP__ +#define AUDIODEVICE_HPP__ + +#include + +class QDataStream; + +// +// abstract base class for audio devices +// +class AudioDevice : public QIODevice +{ +public: + enum Channel {Mono, Left, Right, Both}; // these are mapped to combobox index so don't change + + static char const * toString (Channel c) + { + return Mono == c ? "Mono" : Left == c ? "Left" : Right == c ? "Right" : "Both"; + } + + static Channel fromString (QString const& str) + { + QString s (str.toCaseFolded ().trimmed ().toLatin1 ()); + return "both" == s ? Both : "right" == s ? Right : "left" == s ? Left : Mono; + } + + bool open (OpenMode mode, Channel channel) + { + m_channel = channel; + + // ensure we are unbuffered + return QIODevice::open (mode | QIODevice::Unbuffered); + } + + bool isSequential () const {return true;} + + size_t bytesPerFrame () const {return sizeof (qint16) * (Mono == m_channel ? 1 : 2);} + + Channel channel () const {return m_channel;} + void channel (Channel newChannel) {m_channel = newChannel;} + +protected: + AudioDevice (QObject * parent = 0) + : QIODevice (parent) + { + } + + void store (char const * source, qint64 numFrames, qint16 * dest) + { + qint16 const * begin (reinterpret_cast (source)); + for ( qint16 const * i = begin; i != begin + numFrames * (bytesPerFrame () / sizeof (qint16)); i += bytesPerFrame () / sizeof (qint16)) + { + switch (m_channel) + { + case Mono: + *dest++ = *i; + break; + + case Right: + *dest++ = *(i + 1); + break; + + case Both: // should be able to happen but if it + // does we'll take left + Q_ASSERT (Both == m_channel); + case Left: + *dest++ = *i; + break; + } + } + } + + qint16 * load (qint16 const sample, qint16 * dest) + { + switch (m_channel) + { + case Mono: + *dest++ = sample; + break; + + case Left: + *dest++ = sample; + *dest++ = 0; + break; + + case Right: + *dest++ = 0; + *dest++ = sample; + break; + + case Both: + *dest++ = sample; + *dest++ = sample; + break; + } + return dest; + } + +private: + Channel m_channel; +}; + +Q_DECLARE_METATYPE (AudioDevice::Channel); + +#endif diff --git a/Detector.cpp b/Detector.cpp index 2318e9475..2fe0031a2 100644 --- a/Detector.cpp +++ b/Detector.cpp @@ -6,11 +6,11 @@ #include "commons.h" -Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned bytesPerSignal, QObject * parent) - : QIODevice (parent) +Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, QObject * parent) + : AudioDevice (parent) , m_frameRate (frameRate) , m_period (periodLengthInSeconds) - , m_bytesPerSignal (bytesPerSignal) + , m_framesPerSignal (framesPerSignal) , m_monitoring (false) , m_starting (false) { @@ -37,28 +37,25 @@ void Detector::clear () qint64 Detector::writeData (char const * data, qint64 maxSize) { - Q_ASSERT (!(maxSize % static_cast (sizeof (frame_t)))); // no torn frames - Q_ASSERT (!(reinterpret_cast (data) % __alignof__ (frame_t))); // data is aligned as frame_t would be - - frame_t const * frames (reinterpret_cast (data)); + Q_ASSERT (!(maxSize % static_cast (bytesPerFrame ()))); // no torn frames qint64 framesAcceptable (sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]) - jt9com_.kin); - qint64 framesAccepted (qMin (static_cast (maxSize / sizeof (jt9com_.d2[0])), framesAcceptable)); + qint64 framesAccepted (qMin (static_cast (maxSize / bytesPerFrame ()), framesAcceptable)); - if (framesAccepted < static_cast (maxSize / sizeof (jt9com_.d2[0]))) + if (framesAccepted < static_cast (maxSize / bytesPerFrame ())) { qDebug () << "dropped " << maxSize / sizeof (jt9com_.d2[0]) - framesAccepted << " frames of data on the floor!"; } - qCopy (frames, frames + framesAccepted, &jt9com_.d2[jt9com_.kin]); + store (data, framesAccepted, &jt9com_.d2[jt9com_.kin]); - unsigned lastSignalIndex (jt9com_.kin * sizeof (jt9com_.d2[0]) / m_bytesPerSignal); + unsigned lastSignalIndex (jt9com_.kin / m_framesPerSignal); jt9com_.kin += framesAccepted; - unsigned currentSignalIndex (jt9com_.kin * sizeof (jt9com_.d2[0]) / m_bytesPerSignal); + unsigned currentSignalIndex (jt9com_.kin / m_framesPerSignal); if (currentSignalIndex != lastSignalIndex && m_monitoring) { - Q_EMIT bytesWritten (currentSignalIndex * m_bytesPerSignal); + Q_EMIT framesWritten (currentSignalIndex * m_framesPerSignal); } if (!secondInPeriod ()) diff --git a/Detector.hpp b/Detector.hpp index f842e70b9..8282d7262 100644 --- a/Detector.hpp +++ b/Detector.hpp @@ -1,9 +1,7 @@ #ifndef DETECTOR_HPP__ #define DETECTOR_HPP__ -#include - -#include +#include "AudioDevice.hpp" // // output device that distributes data in predefined chunks via a signal @@ -11,38 +9,28 @@ // the underlying device for this abstraction is just the buffer that // stores samples throughout a receiving period // -class Detector : public QIODevice +class Detector : public AudioDevice { Q_OBJECT; Q_PROPERTY (bool monitoring READ isMonitoring WRITE setMonitoring); -private: - Q_DISABLE_COPY (Detector); - public: // // if the data buffer were not global storage and fixed size then we // might want maximum size passed as constructor arguments // - Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned bytesPerSignal, QObject * parent = 0); + Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, QObject * parent = 0); - bool open () - { - // we only support data consumption and want it as fast as possible - return QIODevice::open (QIODevice::WriteOnly | QIODevice::Unbuffered); - } - - bool isSequential () const - { - return true; - } + bool open (Channel channel = Mono) {return AudioDevice::open (QIODevice::WriteOnly, channel);} bool isMonitoring () const {return m_monitoring;} void setMonitoring (bool newState) {m_monitoring = newState;} bool reset (); + Q_SIGNAL void framesWritten (qint64); + protected: qint64 readData (char * /* data */, qint64 /* maxSize */) { @@ -52,14 +40,12 @@ protected: qint64 writeData (char const * data, qint64 maxSize); private: - typedef qint16 frame_t; - void clear (); // discard buffer contents unsigned secondInPeriod () const; unsigned m_frameRate; unsigned m_period; - unsigned m_bytesPerSignal; + unsigned m_framesPerSignal; bool m_monitoring; bool m_starting; }; diff --git a/Modulator.cpp b/Modulator.cpp index 24f96bf59..6b0fa5072 100644 --- a/Modulator.cpp +++ b/Modulator.cpp @@ -10,6 +10,15 @@ extern float gran(); // Noise generator (for tests only) +// MUST be an integral factor of 2^16 +#define RAMP_INCREMENT 64 + +#if defined (WSJT_SOFT_KEYING) +# define SOFT_KEYING true +#else +# define SOFT_KEYING false +#endif + double const Modulator::m_twoPi = 2.0 * 3.141592653589793238462; // float wpm=20.0; @@ -18,7 +27,7 @@ double const Modulator::m_twoPi = 2.0 * 3.141592653589793238462; unsigned const Modulator::m_nspd = 2048 + 512; // 22.5 WPM Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent) - : QIODevice (parent) + : AudioDevice (parent) , m_frameRate (frameRate) , m_period (periodLengthInSeconds) , m_framesSent (0) @@ -30,11 +39,13 @@ Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObjec qsrand (QDateTime::currentMSecsSinceEpoch()); // Initialize random seed } -void Modulator::send (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, bool synchronize, double dBSNR) +void Modulator::open (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, Channel channel, bool synchronize, double dBSNR) { // Time according to this computer which becomes our base time qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000; + qDebug () << "Modulator: Using soft keying for CW is " << SOFT_KEYING;; + m_symbolsLength = symbolsLength; m_framesSent = 0; @@ -67,16 +78,19 @@ void Modulator::send (unsigned symbolsLength, double framesPerSymbol, unsigned f } // qDebug () << "Modulator: starting at " << m_ic / m_frameRate << " sec, sending " << m_silentFrames << " silent frames"; + + AudioDevice::open (QIODevice::ReadOnly, channel); Q_EMIT stateChanged ((m_state = (synchronize && m_silentFrames) ? Synchronizing : Active)); } qint64 Modulator::readData (char * data, qint64 maxSize) { - Q_ASSERT (!(maxSize % static_cast (sizeof (frame_t)))); // no torn frames - Q_ASSERT (!(reinterpret_cast (data) % __alignof__ (frame_t))); // data is aligned as frame_t would be + Q_ASSERT (!(maxSize % static_cast (bytesPerFrame ()))); // no torn frames + Q_ASSERT (isOpen ()); - frame_t * frames (reinterpret_cast (data)); - qint64 numFrames (maxSize / sizeof (frame_t)); + qint64 numFrames (maxSize / bytesPerFrame ()); + qint16 * samples (reinterpret_cast (data)); + qint16 * end (samples + numFrames * (bytesPerFrame () / sizeof (qint16))); // qDebug () << "Modulator: " << numFrames << " requested, m_ic = " << m_ic << ", tune mode is " << m_tuning; @@ -86,19 +100,16 @@ qint64 Modulator::readData (char * data, qint64 maxSize) { if (m_silentFrames) // send silence up to first second { - frame_t frame; - for (unsigned c = 0; c < NUM_CHANNELS; ++c) - { - frame.channel[c] = 0; // silence - } - numFrames = qMin (m_silentFrames, numFrames); - qFill (frames, frames + numFrames, frame); + for ( ; samples != end; samples = load (0, samples)) // silence + { + } m_silentFrames -= numFrames; - return numFrames * sizeof (frame_t); + return numFrames * bytesPerFrame (); } Q_EMIT stateChanged ((m_state = Active)); + m_ramp = 0; // prepare for CW wave shaping } // fall through @@ -114,7 +125,8 @@ qint64 Modulator::readData (char * data, qint64 maxSize) unsigned const ic0 = m_symbolsLength * 4 * m_nsps; unsigned j (0); qint64 framesGenerated (0); - for (unsigned i = 0; i < numFrames; ++i) + + while (samples != end) { m_phi += m_dphi; if (m_phi > m_twoPi) @@ -122,28 +134,31 @@ qint64 Modulator::readData (char * data, qint64 maxSize) m_phi -= m_twoPi; } - frame_t frame; - for (unsigned c = 0; c < NUM_CHANNELS; ++c) + qint16 sample ((SOFT_KEYING ? qAbs (m_ramp - 1) : (m_ramp ? 32767 : 0)) * qSin (m_phi)); + + j = (m_ic - ic0 - 1) / m_nspd + 1; + bool l0 (icw[j] && icw[j] <= 1); // first element treated specially as it's a count + j = (m_ic - ic0) / m_nspd + 1; + + if ((m_ramp != 0 && m_ramp != std::numeric_limits::min ()) || !!icw[j] != l0) { - frame.channel[c] = std::numeric_limits::max () * qSin (m_phi); + if (!!icw[j] != l0) + { + Q_ASSERT (m_ramp == 0 || m_ramp == std::numeric_limits::min ()); + } + m_ramp += RAMP_INCREMENT; // ramp } - j = (m_ic - ic0) / m_nspd + 1; if (j < NUM_CW_SYMBOLS) // stop condition { - if (!icw[j]) - { - for (unsigned c = 0; c < NUM_CHANNELS; ++c) - { - frame.channel[c] = 0; - } - } + // if (!m_ramp && !icw[j]) + // { + // sample = 0; + // } - frame = postProcessFrame (frame); + samples = load (postProcessSample (sample), samples); - *frames++ = frame; ++framesGenerated; - ++m_ic; } } @@ -154,7 +169,7 @@ qint64 Modulator::readData (char * data, qint64 maxSize) } m_framesSent += framesGenerated; - return framesGenerated * sizeof (frame_t); + return framesGenerated * bytesPerFrame (); } double const baud (12000.0 / m_nsps); @@ -186,15 +201,7 @@ qint64 Modulator::readData (char * data, qint64 maxSize) m_amp = 0.0; } - frame_t frame; - for (unsigned c = 0; c < NUM_CHANNELS; ++c) - { - frame.channel[c] = m_amp * qSin (m_phi); - } - - frame = postProcessFrame (frame); - - *frames++ = frame; + samples = load (postProcessSample (m_amp * qSin (m_phi)), samples); ++m_ic; } @@ -206,7 +213,7 @@ qint64 Modulator::readData (char * data, qint64 maxSize) // no CW ID to send Q_EMIT stateChanged ((m_state = Idle)); m_framesSent += numFrames; - return numFrames * sizeof (frame_t); + return numFrames * bytesPerFrame (); } m_phi = 0.0; @@ -214,7 +221,7 @@ qint64 Modulator::readData (char * data, qint64 maxSize) // done for this chunk - continue on next call m_framesSent += numFrames; - return numFrames * sizeof (frame_t); + return numFrames * bytesPerFrame (); } Q_EMIT stateChanged ((m_state = Idle)); // fall through @@ -227,35 +234,24 @@ qint64 Modulator::readData (char * data, qint64 maxSize) return 0; } -Modulator::frame_t Modulator::postProcessFrame (frame_t frame) const +qint16 Modulator::postProcessSample (qint16 sample) const { if (m_muted) // silent frame { - for (unsigned c = 0; c < NUM_CHANNELS; ++c) - { - frame.channel[c] = 0; - } + sample = 0; } else if (m_addNoise) { - qint32 f[NUM_CHANNELS]; - for (unsigned c = 0; c < NUM_CHANNELS; ++c) + qint32 s = m_fac * (gran () + sample * m_snr / 32768.0); + if (s > std::numeric_limits::max ()) { - f[c] = m_fac * (gran () + frame.channel[c] * m_snr / 32768.0); - if (f[c] > std::numeric_limits::max ()) - { - f[c] = std::numeric_limits::max (); - } - if (f[c] < std::numeric_limits::min ()) - { - f[c] = std::numeric_limits::min (); - } + s = std::numeric_limits::max (); } - - for (unsigned c = 0; c < NUM_CHANNELS; ++c) + if (s < std::numeric_limits::min ()) { - frame.channel[c] = f[c]; + s = std::numeric_limits::min (); } + sample = s; } - return frame; + return sample; } diff --git a/Modulator.hpp b/Modulator.hpp index 7a9f941ea..250a3dfc3 100644 --- a/Modulator.hpp +++ b/Modulator.hpp @@ -1,7 +1,7 @@ #ifndef MODULATOR_HPP__ #define MODULATOR_HPP__ -#include +#include "AudioDevice.hpp" #ifdef UNIX # define NUM_CHANNELS 2 @@ -16,7 +16,7 @@ // Output can be muted while underway, preserving waveform timing when // transmission is resumed. // -class Modulator : public QIODevice +class Modulator : public AudioDevice { Q_OBJECT; @@ -24,33 +24,18 @@ class Modulator : public QIODevice Q_PROPERTY (bool tuning READ isTuning WRITE tune); Q_PROPERTY (bool muted READ isMuted WRITE mute); -private: - Q_DISABLE_COPY (Modulator); - public: + enum ModulatorState {Synchronizing, Active, Idle}; + Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent = 0); - bool open () {return QIODevice::open (QIODevice::ReadOnly | QIODevice::Unbuffered);} - - Q_SLOT void send (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, bool synchronize = true, double dBSNR = 99.); - - Q_SLOT void stop () {Q_EMIT stateChanged ((m_state = Idle));} + Q_SLOT void open (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, AudioDevice::Channel, bool synchronize = true, double dBSNR = 99.); bool isTuning () const {return m_tuning;} - Q_SLOT void tune (bool newState = true) {m_tuning = newState;} - bool isMuted () const {return m_muted;} - Q_SLOT void mute (bool newState = true) {m_muted = newState;} - unsigned frequency () const {return m_frequency;} - Q_SLOT void setFrequency (unsigned newFrequency) {m_frequency = newFrequency;} - - enum ModulatorState {Synchronizing, Active, Idle}; - Q_SIGNAL void stateChanged (ModulatorState); bool isActive () const {return m_state != Idle;} - bool isSequential () const {return true;} - protected: qint64 readData (char * data, qint64 maxSize); qint64 writeData (char const * /* data */, qint64 /* maxSize */) @@ -59,12 +44,22 @@ protected: } private: - typedef struct + /* private because we epect to run in a thread and don't want direct + C++ calls made, instead they must be invoked via the Qt + signal/slot mechanism which is thread safe */ + Q_SLOT void close () { - qint16 channel[NUM_CHANNELS]; - } frame_t; + Q_EMIT stateChanged ((m_state = Idle)); + AudioDevice::close (); + } - frame_t postProcessFrame (frame_t frame) const; + Q_SLOT void tune (bool newState = true) {m_tuning = newState;} + Q_SLOT void mute (bool newState = true) {m_muted = newState;} + Q_SLOT void setFrequency (unsigned newFrequency) {m_frequency = newFrequency;} + Q_SIGNAL void stateChanged (ModulatorState); + +private: + qint16 postProcessSample (qint16 sample) const; unsigned m_symbolsLength; @@ -88,6 +83,7 @@ private: unsigned m_ic; double m_fac; unsigned m_isym0; + qint16 m_ramp; }; #endif diff --git a/PSKReporter.h b/PSKReporter.h index a6c52c488..cb03bcaff 100644 --- a/PSKReporter.h +++ b/PSKReporter.h @@ -1,127 +1,127 @@ -#pragma once - -// Main header file for the external interface to the PSK Reporter API -// For documentation see http://psk.gladstonefamily.net/PSKReporterAPI.pdf - -/* - -Copyright (c) 2008 Philip Gladstone - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - */ - - -#ifdef _DLL_OPTION_PSKREPORTER_EXPORT -#define DllImportExport __declspec ( dllexport ) -#else -#define DllImportExport __declspec ( dllimport ) -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -#define REPORTER_SOURCE_MASK 0x07 -#define REPORTER_SOURCE_AUTOMATIC 0x01 -#define REPORTER_SOURCE_LOG 0x02 -#define REPORTER_SOURCE_MANUAL 0x03 -#define REPORTER_SOURCE_TENTATIVE 0x40 -#define REPORTER_SOURCE_TEST 0x80 - -typedef struct { - wchar_t hostname[256]; - wchar_t port[32]; - bool connected; - unsigned int callsigns_sent; - unsigned int callsigns_buffered; - unsigned int callsigns_discarded; - unsigned int last_send_time; - unsigned int next_send_time; - wchar_t last_callsign_queued[24]; - unsigned int bytes_sent; - unsigned int bytes_sent_total; - unsigned int packets_sent; - unsigned int packets_sent_total; -} REPORTER_STATISTICS; - - - - -unsigned long DllImportExport __cdecl ReporterInitialize( - const wchar_t *hostname, - const wchar_t *port -); - -unsigned long DllImportExport __cdecl ReporterSeenCallsign( - const wchar_t *remoteInformation, - const wchar_t *localInformation, - unsigned long flags -); - -unsigned long DllImportExport __cdecl ReporterTickle( -); - -unsigned long DllImportExport __cdecl ReporterGetInformation( - wchar_t *buffer, - unsigned long maxlen -); - -unsigned long DllImportExport __cdecl ReporterGetStatistics( - REPORTER_STATISTICS *buffer, - unsigned long maxlen -); - -unsigned long DllImportExport __cdecl ReporterUninitialize( -); - - -unsigned long DllImportExport __stdcall ReporterInitializeSTD( - const char *hostname, - const char *port -); - -unsigned long DllImportExport __stdcall ReporterSeenCallsignSTD( - const char *remoteInformation, - const char *localInformation, - unsigned long flags -); - -unsigned long DllImportExport __stdcall ReporterTickleSTD( -); - -unsigned long DllImportExport __stdcall ReporterGetInformationSTD( - char *buffer, - unsigned long maxlen -); - -unsigned long DllImportExport __stdcall ReporterGetStatisticsSTD( - REPORTER_STATISTICS *buffer, - unsigned long maxlen -); - -unsigned long DllImportExport __stdcall ReporterUninitializeSTD( -); - -#ifdef __cplusplus -} -#endif - - +#pragma once + +// Main header file for the external interface to the PSK Reporter API +// For documentation see http://psk.gladstonefamily.net/PSKReporterAPI.pdf + +/* + +Copyright (c) 2008 Philip Gladstone + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + */ + + +#ifdef _DLL_OPTION_PSKREPORTER_EXPORT +#define DllImportExport __declspec ( dllexport ) +#else +#define DllImportExport __declspec ( dllimport ) +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#define REPORTER_SOURCE_MASK 0x07 +#define REPORTER_SOURCE_AUTOMATIC 0x01 +#define REPORTER_SOURCE_LOG 0x02 +#define REPORTER_SOURCE_MANUAL 0x03 +#define REPORTER_SOURCE_TENTATIVE 0x40 +#define REPORTER_SOURCE_TEST 0x80 + +typedef struct { + wchar_t hostname[256]; + wchar_t port[32]; + bool connected; + unsigned int callsigns_sent; + unsigned int callsigns_buffered; + unsigned int callsigns_discarded; + unsigned int last_send_time; + unsigned int next_send_time; + wchar_t last_callsign_queued[24]; + unsigned int bytes_sent; + unsigned int bytes_sent_total; + unsigned int packets_sent; + unsigned int packets_sent_total; +} REPORTER_STATISTICS; + + + + +unsigned long DllImportExport __cdecl ReporterInitialize( + const wchar_t *hostname, + const wchar_t *port +); + +unsigned long DllImportExport __cdecl ReporterSeenCallsign( + const wchar_t *remoteInformation, + const wchar_t *localInformation, + unsigned long flags +); + +unsigned long DllImportExport __cdecl ReporterTickle( +); + +unsigned long DllImportExport __cdecl ReporterGetInformation( + wchar_t *buffer, + unsigned long maxlen +); + +unsigned long DllImportExport __cdecl ReporterGetStatistics( + REPORTER_STATISTICS *buffer, + unsigned long maxlen +); + +unsigned long DllImportExport __cdecl ReporterUninitialize( +); + + +unsigned long DllImportExport __stdcall ReporterInitializeSTD( + const char *hostname, + const char *port +); + +unsigned long DllImportExport __stdcall ReporterSeenCallsignSTD( + const char *remoteInformation, + const char *localInformation, + unsigned long flags +); + +unsigned long DllImportExport __stdcall ReporterTickleSTD( +); + +unsigned long DllImportExport __stdcall ReporterGetInformationSTD( + char *buffer, + unsigned long maxlen +); + +unsigned long DllImportExport __stdcall ReporterGetStatisticsSTD( + REPORTER_STATISTICS *buffer, + unsigned long maxlen +); + +unsigned long DllImportExport __stdcall ReporterUninitializeSTD( +); + +#ifdef __cplusplus +} +#endif + + diff --git a/devsetup.cpp b/devsetup.cpp index 84412864c..8d7d0dfc6 100644 --- a/devsetup.cpp +++ b/devsetup.cpp @@ -1,13 +1,17 @@ #include "devsetup.h" +#include "ui_devsetup.h" + +#include +#include +#include + #include #include #include #include #include -#define MAXDEVICES 100 - extern double dFreq[16]; qint32 g2_iptt; qint32 g2_COMportOpen; @@ -15,10 +19,11 @@ qint32 g2_COMportOpen; //----------------------------------------------------------- DevSetup() DevSetup::DevSetup(QWidget *parent) : QDialog(parent) + , ui (new Ui::DevSetup) , m_audioInputDevices (QAudioDeviceInfo::availableDevices (QAudio::AudioInput)) , m_audioOutputDevices (QAudioDeviceInfo::availableDevices (QAudio::AudioOutput)) { - ui.setupUi(this); //setup the dialog form + ui->setupUi(this); //setup the dialog form m_restartSoundIn=false; m_restartSoundOut=false; m_firstCall=true; @@ -42,182 +47,165 @@ void DevSetup::initDlg() settings.endGroup(); // - // load combo boxes with setup choices + // load combo boxes with audio setup choices // - { - int currentIndex = -1; - int defaultIndex = 0; - for (AudioDevices::const_iterator p = m_audioInputDevices.begin (); p != m_audioInputDevices.end (); ++p) - { - ui.comboBoxSndIn->addItem (p->deviceName ()); - if (*p == m_audioInputDevice) - { - currentIndex = p - m_audioInputDevices.begin (); - } - else if (*p == QAudioDeviceInfo::defaultInputDevice ()) - { - defaultIndex = p - m_audioInputDevices.begin (); - } - } - ui.comboBoxSndIn->setCurrentIndex (currentIndex != -1 ? currentIndex : defaultIndex); - } + loadAudioDevices (m_audioInputDevices, ui->comboBoxSndIn); + loadAudioDevices (m_audioOutputDevices, ui->comboBoxSndOut); { - int currentIndex = -1; - int defaultIndex = 0; - for (AudioDevices::const_iterator p = m_audioOutputDevices.begin (); p != m_audioOutputDevices.end (); ++p) - { - ui.comboBoxSndOut->addItem (p->deviceName ()); - if (*p == m_audioOutputDevice) - { - currentIndex = p - m_audioOutputDevices.begin (); - } - else if (*p == QAudioDeviceInfo::defaultOutputDevice ()) - { - defaultIndex = p - m_audioOutputDevices.begin (); - } - } - ui.comboBoxSndOut->setCurrentIndex (currentIndex != -1 ? currentIndex : defaultIndex); + using namespace std::tr1; + using namespace std::tr1::placeholders; + + function cb (bind (&DevSetup::updateAudioChannels, this, ui->comboBoxSndIn, _1, ui->audioInputChannel, false)); + connect (ui->comboBoxSndIn, static_cast (&QComboBox::currentIndexChanged), cb); + cb = bind (&DevSetup::updateAudioChannels, this, ui->comboBoxSndOut, _1, ui->audioOutputChannel, true); + connect (ui->comboBoxSndOut, static_cast (&QComboBox::currentIndexChanged), cb); + + updateAudioChannels (ui->comboBoxSndIn, ui->comboBoxSndIn->currentIndex (), ui->audioInputChannel, false); + updateAudioChannels (ui->comboBoxSndOut, ui->comboBoxSndOut->currentIndex (), ui->audioOutputChannel, true); + + ui->audioInputChannel->setCurrentIndex (m_audioInputChannel); + ui->audioOutputChannel->setCurrentIndex (m_audioOutputChannel); } enumerateRigs (); - QPalette pal(ui.myCallEntry->palette()); + QPalette pal(ui->myCallEntry->palette()); if(m_myCall=="") { pal.setColor(QPalette::Base,"#ffccff"); } else { pal.setColor(QPalette::Base,Qt::white); } - ui.myCallEntry->setPalette(pal); - ui.myGridEntry->setPalette(pal); - ui.myCallEntry->setText(m_myCall); - ui.myGridEntry->setText(m_myGrid); + ui->myCallEntry->setPalette(pal); + ui->myGridEntry->setPalette(pal); + ui->myCallEntry->setText(m_myCall); + ui->myGridEntry->setText(m_myGrid); - ui.idIntSpinBox->setValue(m_idInt); - ui.pttMethodComboBox->setCurrentIndex(m_pttMethodIndex); - ui.saveDirEntry->setText(m_saveDir); - ui.cbID73->setChecked(m_After73); - ui.cbPSKReporter->setChecked(m_pskReporter); - ui.cbSplit->setChecked(m_bSplit and m_catEnabled); - ui.cbXIT->setChecked(m_bXIT); - ui.cbXIT->setVisible(false); + ui->idIntSpinBox->setValue(m_idInt); + ui->pttMethodComboBox->setCurrentIndex(m_pttMethodIndex); + ui->saveDirEntry->setText(m_saveDir); + ui->cbID73->setChecked(m_After73); + ui->cbPSKReporter->setChecked(m_pskReporter); + ui->cbSplit->setChecked(m_bSplit and m_catEnabled); + ui->cbXIT->setChecked(m_bXIT); + ui->cbXIT->setVisible(false); enableWidgets(); - ui.catPortComboBox->setCurrentIndex(m_catPortIndex); - ui.serialRateComboBox->setCurrentIndex(m_serialRateIndex); - ui.dataBitsComboBox->setCurrentIndex(m_dataBitsIndex); - ui.stopBitsComboBox->setCurrentIndex(m_stopBitsIndex); - ui.handshakeComboBox->setCurrentIndex(m_handshakeIndex); - ui.rbData->setChecked(m_pttData); - ui.pollSpinBox->setValue(m_poll); + ui->catPortComboBox->setCurrentIndex(m_catPortIndex); + ui->serialRateComboBox->setCurrentIndex(m_serialRateIndex); + ui->dataBitsComboBox->setCurrentIndex(m_dataBitsIndex); + ui->stopBitsComboBox->setCurrentIndex(m_stopBitsIndex); + ui->handshakeComboBox->setCurrentIndex(m_handshakeIndex); + ui->rbData->setChecked(m_pttData); + ui->pollSpinBox->setValue(m_poll); // PY2SDR -- Per OS serial port names m_tmp=m_pttPort; - ui.pttComboBox->clear(); - ui.catPortComboBox->clear(); - ui.pttComboBox->addItem("None"); - ui.catPortComboBox->addItem("None"); + ui->pttComboBox->clear(); + ui->catPortComboBox->clear(); + ui->pttComboBox->addItem("None"); + ui->catPortComboBox->addItem("None"); #ifdef WIN32 for ( int i = 1; i < 100; i++ ) { - ui.pttComboBox->addItem("COM" + QString::number(i)); - ui.catPortComboBox->addItem("COM" + QString::number(i)); + ui->pttComboBox->addItem("COM" + QString::number(i)); + ui->catPortComboBox->addItem("COM" + QString::number(i)); } - ui.pttComboBox->addItem("USB"); - ui.catPortComboBox->addItem("USB"); + ui->pttComboBox->addItem("USB"); + ui->catPortComboBox->addItem("USB"); #else - ui.catPortComboBox->addItem("/dev/ttyS0"); - ui.catPortComboBox->addItem("/dev/ttyS1"); - ui.catPortComboBox->addItem("/dev/ttyS2"); - ui.catPortComboBox->addItem("/dev/ttyS3"); - ui.catPortComboBox->addItem("/dev/ttyS4"); - ui.catPortComboBox->addItem("/dev/ttyS5"); - ui.catPortComboBox->addItem("/dev/ttyS6"); - ui.catPortComboBox->addItem("/dev/ttyS7"); - ui.catPortComboBox->addItem("/dev/ttyUSB0"); - ui.catPortComboBox->addItem("/dev/ttyUSB1"); - ui.catPortComboBox->addItem("/dev/ttyUSB2"); - ui.catPortComboBox->addItem("/dev/ttyUSB3"); - ui.catPortComboBox->addItem(catPortDriver); + ui->catPortComboBox->addItem("/dev/ttyS0"); + ui->catPortComboBox->addItem("/dev/ttyS1"); + ui->catPortComboBox->addItem("/dev/ttyS2"); + ui->catPortComboBox->addItem("/dev/ttyS3"); + ui->catPortComboBox->addItem("/dev/ttyS4"); + ui->catPortComboBox->addItem("/dev/ttyS5"); + ui->catPortComboBox->addItem("/dev/ttyS6"); + ui->catPortComboBox->addItem("/dev/ttyS7"); + ui->catPortComboBox->addItem("/dev/ttyUSB0"); + ui->catPortComboBox->addItem("/dev/ttyUSB1"); + ui->catPortComboBox->addItem("/dev/ttyUSB2"); + ui->catPortComboBox->addItem("/dev/ttyUSB3"); + ui->catPortComboBox->addItem(catPortDriver); - ui.pttComboBox->addItem("/dev/ttyS0"); - ui.pttComboBox->addItem("/dev/ttyS1"); - ui.pttComboBox->addItem("/dev/ttyS2"); - ui.pttComboBox->addItem("/dev/ttyS3"); - ui.pttComboBox->addItem("/dev/ttyS4"); - ui.pttComboBox->addItem("/dev/ttyS5"); - ui.pttComboBox->addItem("/dev/ttyS6"); - ui.pttComboBox->addItem("/dev/ttyS7"); - ui.pttComboBox->addItem("/dev/ttyUSB0"); - ui.pttComboBox->addItem("/dev/ttyUSB1"); - ui.pttComboBox->addItem("/dev/ttyUSB2"); - ui.pttComboBox->addItem("/dev/ttyUSB3"); + ui->pttComboBox->addItem("/dev/ttyS0"); + ui->pttComboBox->addItem("/dev/ttyS1"); + ui->pttComboBox->addItem("/dev/ttyS2"); + ui->pttComboBox->addItem("/dev/ttyS3"); + ui->pttComboBox->addItem("/dev/ttyS4"); + ui->pttComboBox->addItem("/dev/ttyS5"); + ui->pttComboBox->addItem("/dev/ttyS6"); + ui->pttComboBox->addItem("/dev/ttyS7"); + ui->pttComboBox->addItem("/dev/ttyUSB0"); + ui->pttComboBox->addItem("/dev/ttyUSB1"); + ui->pttComboBox->addItem("/dev/ttyUSB2"); + ui->pttComboBox->addItem("/dev/ttyUSB3"); #endif - ui.pttComboBox->setCurrentIndex(m_tmp); - ui.catPortComboBox->setCurrentIndex(m_catPortIndex); + ui->pttComboBox->setCurrentIndex(m_tmp); + ui->catPortComboBox->setCurrentIndex(m_catPortIndex); int n=m_macro.length(); - if(n>=1) ui.macro1->setText(m_macro[0].toUpper()); - if(n>=2) ui.macro2->setText(m_macro[1].toUpper()); - if(n>=3) ui.macro3->setText(m_macro[2].toUpper()); - if(n>=4) ui.macro4->setText(m_macro[3].toUpper()); - if(n>=5) ui.macro5->setText(m_macro[4].toUpper()); - if(n>=6) ui.macro6->setText(m_macro[5].toUpper()); - if(n>=7) ui.macro7->setText(m_macro[6].toUpper()); - if(n>=8) ui.macro8->setText(m_macro[7].toUpper()); - if(n>=8) ui.macro9->setText(m_macro[8].toUpper()); - if(n>=10) ui.macro10->setText(m_macro[9].toUpper()); + if(n>=1) ui->macro1->setText(m_macro[0].toUpper()); + if(n>=2) ui->macro2->setText(m_macro[1].toUpper()); + if(n>=3) ui->macro3->setText(m_macro[2].toUpper()); + if(n>=4) ui->macro4->setText(m_macro[3].toUpper()); + if(n>=5) ui->macro5->setText(m_macro[4].toUpper()); + if(n>=6) ui->macro6->setText(m_macro[5].toUpper()); + if(n>=7) ui->macro7->setText(m_macro[6].toUpper()); + if(n>=8) ui->macro8->setText(m_macro[7].toUpper()); + if(n>=8) ui->macro9->setText(m_macro[8].toUpper()); + if(n>=10) ui->macro10->setText(m_macro[9].toUpper()); - ui.f1->setText(m_dFreq[0]); - ui.f2->setText(m_dFreq[1]); - ui.f3->setText(m_dFreq[2]); - ui.f4->setText(m_dFreq[3]); - ui.f5->setText(m_dFreq[4]); - ui.f6->setText(m_dFreq[5]); - ui.f7->setText(m_dFreq[6]); - ui.f8->setText(m_dFreq[7]); - ui.f9->setText(m_dFreq[8]); - ui.f10->setText(m_dFreq[9]); - ui.f11->setText(m_dFreq[10]); - ui.f12->setText(m_dFreq[11]); - ui.f13->setText(m_dFreq[12]); - ui.f14->setText(m_dFreq[13]); - ui.f15->setText(m_dFreq[14]); - ui.f16->setText(m_dFreq[15]); + ui->f1->setText(m_dFreq[0]); + ui->f2->setText(m_dFreq[1]); + ui->f3->setText(m_dFreq[2]); + ui->f4->setText(m_dFreq[3]); + ui->f5->setText(m_dFreq[4]); + ui->f6->setText(m_dFreq[5]); + ui->f7->setText(m_dFreq[6]); + ui->f8->setText(m_dFreq[7]); + ui->f9->setText(m_dFreq[8]); + ui->f10->setText(m_dFreq[9]); + ui->f11->setText(m_dFreq[10]); + ui->f12->setText(m_dFreq[11]); + ui->f13->setText(m_dFreq[12]); + ui->f14->setText(m_dFreq[13]); + ui->f15->setText(m_dFreq[14]); + ui->f16->setText(m_dFreq[15]); - ui.AntDescription1->setText(m_antDescription[0]); - ui.AntDescription2->setText(m_antDescription[1]); - ui.AntDescription3->setText(m_antDescription[2]); - ui.AntDescription4->setText(m_antDescription[3]); - ui.AntDescription5->setText(m_antDescription[4]); - ui.AntDescription6->setText(m_antDescription[5]); - ui.AntDescription7->setText(m_antDescription[6]); - ui.AntDescription8->setText(m_antDescription[7]); - ui.AntDescription9->setText(m_antDescription[8]); - ui.AntDescription10->setText(m_antDescription[9]); - ui.AntDescription11->setText(m_antDescription[10]); - ui.AntDescription12->setText(m_antDescription[11]); - ui.AntDescription13->setText(m_antDescription[12]); - ui.AntDescription14->setText(m_antDescription[13]); - ui.AntDescription15->setText(m_antDescription[14]); - ui.AntDescription16->setText(m_antDescription[15]); + ui->AntDescription1->setText(m_antDescription[0]); + ui->AntDescription2->setText(m_antDescription[1]); + ui->AntDescription3->setText(m_antDescription[2]); + ui->AntDescription4->setText(m_antDescription[3]); + ui->AntDescription5->setText(m_antDescription[4]); + ui->AntDescription6->setText(m_antDescription[5]); + ui->AntDescription7->setText(m_antDescription[6]); + ui->AntDescription8->setText(m_antDescription[7]); + ui->AntDescription9->setText(m_antDescription[8]); + ui->AntDescription10->setText(m_antDescription[9]); + ui->AntDescription11->setText(m_antDescription[10]); + ui->AntDescription12->setText(m_antDescription[11]); + ui->AntDescription13->setText(m_antDescription[12]); + ui->AntDescription14->setText(m_antDescription[13]); + ui->AntDescription15->setText(m_antDescription[14]); + ui->AntDescription16->setText(m_antDescription[15]); - ui.Band1->setText(m_bandDescription[0]); - ui.Band2->setText(m_bandDescription[1]); - ui.Band3->setText(m_bandDescription[2]); - ui.Band4->setText(m_bandDescription[3]); - ui.Band5->setText(m_bandDescription[4]); - ui.Band6->setText(m_bandDescription[5]); - ui.Band7->setText(m_bandDescription[6]); - ui.Band8->setText(m_bandDescription[7]); - ui.Band9->setText(m_bandDescription[8]); - ui.Band10->setText(m_bandDescription[9]); - ui.Band11->setText(m_bandDescription[10]); - ui.Band12->setText(m_bandDescription[11]); - ui.Band13->setText(m_bandDescription[12]); - ui.Band14->setText(m_bandDescription[13]); - ui.Band15->setText(m_bandDescription[14]); - ui.Band16->setText(m_bandDescription[15]); + ui->Band1->setText(m_bandDescription[0]); + ui->Band2->setText(m_bandDescription[1]); + ui->Band3->setText(m_bandDescription[2]); + ui->Band4->setText(m_bandDescription[3]); + ui->Band5->setText(m_bandDescription[4]); + ui->Band6->setText(m_bandDescription[5]); + ui->Band7->setText(m_bandDescription[6]); + ui->Band8->setText(m_bandDescription[7]); + ui->Band9->setText(m_bandDescription[8]); + ui->Band10->setText(m_bandDescription[9]); + ui->Band11->setText(m_bandDescription[10]); + ui->Band12->setText(m_bandDescription[11]); + ui->Band13->setText(m_bandDescription[12]); + ui->Band14->setText(m_bandDescription[13]); + ui->Band15->setText(m_bandDescription[14]); + ui->Band16->setText(m_bandDescription[15]); } @@ -228,90 +216,106 @@ void DevSetup::accept() // Check to see whether SoundInThread must be restarted, // and save user parameters. - if (m_audioInputDevice != m_audioInputDevices[ui.comboBoxSndIn->currentIndex ()]) + m_restartSoundIn = m_restartSoundOut = false; + + if (m_audioInputDevice != m_audioInputDevices[ui->comboBoxSndIn->currentIndex ()]) { - m_audioInputDevice = m_audioInputDevices[ui.comboBoxSndIn->currentIndex ()]; + m_audioInputDevice = m_audioInputDevices[ui->comboBoxSndIn->currentIndex ()]; m_restartSoundIn = true; } - if (m_audioOutputDevice != m_audioOutputDevices[ui.comboBoxSndOut->currentIndex ()]) + if (m_audioOutputDevice != m_audioOutputDevices[ui->comboBoxSndOut->currentIndex ()]) { - m_audioOutputDevice = m_audioOutputDevices[ui.comboBoxSndOut->currentIndex ()]; + m_audioOutputDevice = m_audioOutputDevices[ui->comboBoxSndOut->currentIndex ()]; m_restartSoundOut = true; } - m_myCall=ui.myCallEntry->text(); - m_myGrid=ui.myGridEntry->text(); - m_idInt=ui.idIntSpinBox->value(); - m_pttMethodIndex=ui.pttMethodComboBox->currentIndex(); - m_pttPort=ui.pttComboBox->currentIndex(); - m_saveDir=ui.saveDirEntry->text(); + if (m_audioInputChannel != static_cast (ui->audioInputChannel->currentIndex ())) + { + m_audioInputChannel = static_cast (ui->audioInputChannel->currentIndex ()); + m_restartSoundIn = true; + } + Q_ASSERT (m_audioInputChannel <= AudioDevice::Right); + + if (m_audioOutputChannel != static_cast (ui->audioOutputChannel->currentIndex ())) + { + m_audioOutputChannel = static_cast (ui->audioOutputChannel->currentIndex ()); + m_restartSoundOut = true; + } + Q_ASSERT (m_audioOutputChannel <= AudioDevice::Both); + + m_myCall=ui->myCallEntry->text(); + m_myGrid=ui->myGridEntry->text(); + m_idInt=ui->idIntSpinBox->value(); + m_pttMethodIndex=ui->pttMethodComboBox->currentIndex(); + m_pttPort=ui->pttComboBox->currentIndex(); + m_saveDir=ui->saveDirEntry->text(); m_macro.clear(); - m_macro.append(ui.macro1->text()); - m_macro.append(ui.macro2->text()); - m_macro.append(ui.macro3->text()); - m_macro.append(ui.macro4->text()); - m_macro.append(ui.macro5->text()); - m_macro.append(ui.macro6->text()); - m_macro.append(ui.macro7->text()); - m_macro.append(ui.macro8->text()); - m_macro.append(ui.macro9->text()); - m_macro.append(ui.macro10->text()); + m_macro.append(ui->macro1->text()); + m_macro.append(ui->macro2->text()); + m_macro.append(ui->macro3->text()); + m_macro.append(ui->macro4->text()); + m_macro.append(ui->macro5->text()); + m_macro.append(ui->macro6->text()); + m_macro.append(ui->macro7->text()); + m_macro.append(ui->macro8->text()); + m_macro.append(ui->macro9->text()); + m_macro.append(ui->macro10->text()); m_dFreq.clear(); - m_dFreq.append(ui.f1->text()); - m_dFreq.append(ui.f2->text()); - m_dFreq.append(ui.f3->text()); - m_dFreq.append(ui.f4->text()); - m_dFreq.append(ui.f5->text()); - m_dFreq.append(ui.f6->text()); - m_dFreq.append(ui.f7->text()); - m_dFreq.append(ui.f8->text()); - m_dFreq.append(ui.f9->text()); - m_dFreq.append(ui.f10->text()); - m_dFreq.append(ui.f11->text()); - m_dFreq.append(ui.f12->text()); - m_dFreq.append(ui.f13->text()); - m_dFreq.append(ui.f14->text()); - m_dFreq.append(ui.f15->text()); - m_dFreq.append(ui.f16->text()); + m_dFreq.append(ui->f1->text()); + m_dFreq.append(ui->f2->text()); + m_dFreq.append(ui->f3->text()); + m_dFreq.append(ui->f4->text()); + m_dFreq.append(ui->f5->text()); + m_dFreq.append(ui->f6->text()); + m_dFreq.append(ui->f7->text()); + m_dFreq.append(ui->f8->text()); + m_dFreq.append(ui->f9->text()); + m_dFreq.append(ui->f10->text()); + m_dFreq.append(ui->f11->text()); + m_dFreq.append(ui->f12->text()); + m_dFreq.append(ui->f13->text()); + m_dFreq.append(ui->f14->text()); + m_dFreq.append(ui->f15->text()); + m_dFreq.append(ui->f16->text()); m_antDescription.clear(); - m_antDescription.append(ui.AntDescription1->text()); - m_antDescription.append(ui.AntDescription2->text()); - m_antDescription.append(ui.AntDescription3->text()); - m_antDescription.append(ui.AntDescription4->text()); - m_antDescription.append(ui.AntDescription5->text()); - m_antDescription.append(ui.AntDescription6->text()); - m_antDescription.append(ui.AntDescription7->text()); - m_antDescription.append(ui.AntDescription8->text()); - m_antDescription.append(ui.AntDescription9->text()); - m_antDescription.append(ui.AntDescription10->text()); - m_antDescription.append(ui.AntDescription11->text()); - m_antDescription.append(ui.AntDescription12->text()); - m_antDescription.append(ui.AntDescription13->text()); - m_antDescription.append(ui.AntDescription14->text()); - m_antDescription.append(ui.AntDescription15->text()); - m_antDescription.append(ui.AntDescription16->text()); + m_antDescription.append(ui->AntDescription1->text()); + m_antDescription.append(ui->AntDescription2->text()); + m_antDescription.append(ui->AntDescription3->text()); + m_antDescription.append(ui->AntDescription4->text()); + m_antDescription.append(ui->AntDescription5->text()); + m_antDescription.append(ui->AntDescription6->text()); + m_antDescription.append(ui->AntDescription7->text()); + m_antDescription.append(ui->AntDescription8->text()); + m_antDescription.append(ui->AntDescription9->text()); + m_antDescription.append(ui->AntDescription10->text()); + m_antDescription.append(ui->AntDescription11->text()); + m_antDescription.append(ui->AntDescription12->text()); + m_antDescription.append(ui->AntDescription13->text()); + m_antDescription.append(ui->AntDescription14->text()); + m_antDescription.append(ui->AntDescription15->text()); + m_antDescription.append(ui->AntDescription16->text()); m_bandDescription.clear(); - m_bandDescription.append(ui.Band1->text()); - m_bandDescription.append(ui.Band2->text()); - m_bandDescription.append(ui.Band3->text()); - m_bandDescription.append(ui.Band4->text()); - m_bandDescription.append(ui.Band5->text()); - m_bandDescription.append(ui.Band6->text()); - m_bandDescription.append(ui.Band7->text()); - m_bandDescription.append(ui.Band8->text()); - m_bandDescription.append(ui.Band9->text()); - m_bandDescription.append(ui.Band10->text()); - m_bandDescription.append(ui.Band11->text()); - m_bandDescription.append(ui.Band12->text()); - m_bandDescription.append(ui.Band13->text()); - m_bandDescription.append(ui.Band14->text()); - m_bandDescription.append(ui.Band15->text()); - m_bandDescription.append(ui.Band16->text()); + m_bandDescription.append(ui->Band1->text()); + m_bandDescription.append(ui->Band2->text()); + m_bandDescription.append(ui->Band3->text()); + m_bandDescription.append(ui->Band4->text()); + m_bandDescription.append(ui->Band5->text()); + m_bandDescription.append(ui->Band6->text()); + m_bandDescription.append(ui->Band7->text()); + m_bandDescription.append(ui->Band8->text()); + m_bandDescription.append(ui->Band9->text()); + m_bandDescription.append(ui->Band10->text()); + m_bandDescription.append(ui->Band11->text()); + m_bandDescription.append(ui->Band12->text()); + m_bandDescription.append(ui->Band13->text()); + m_bandDescription.append(ui->Band14->text()); + m_bandDescription.append(ui->Band15->text()); + m_bandDescription.append(ui->Band16->text()); if(m_bRigOpen) { @@ -338,39 +342,39 @@ void DevSetup::msgBox(QString t) //msgBox void DevSetup::on_myCallEntry_editingFinished() { - QString t=ui.myCallEntry->text(); - ui.myCallEntry->setText(t.toUpper()); + QString t=ui->myCallEntry->text(); + ui->myCallEntry->setText(t.toUpper()); } void DevSetup::on_myGridEntry_editingFinished() { - QString t=ui.myGridEntry->text(); + QString t=ui->myGridEntry->text(); t=t.mid(0,4).toUpper()+t.mid(4,2).toLower(); - ui.myGridEntry->setText(t); + ui->myGridEntry->setText(t); } void DevSetup::setEnableAntennaDescriptions(bool enable) { - ui.AntDescription1->setEnabled(enable); - ui.AntDescription2->setEnabled(enable); - ui.AntDescription3->setEnabled(enable); - ui.AntDescription4->setEnabled(enable); - ui.AntDescription5->setEnabled(enable); - ui.AntDescription6->setEnabled(enable); - ui.AntDescription7->setEnabled(enable); - ui.AntDescription8->setEnabled(enable); - ui.AntDescription9->setEnabled(enable); - ui.AntDescription10->setEnabled(enable); - ui.AntDescription11->setEnabled(enable); - ui.AntDescription12->setEnabled(enable); - ui.AntDescription13->setEnabled(enable); - ui.AntDescription14->setEnabled(enable); - ui.AntDescription15->setEnabled(enable); - ui.AntDescription16->setEnabled(enable); + ui->AntDescription1->setEnabled(enable); + ui->AntDescription2->setEnabled(enable); + ui->AntDescription3->setEnabled(enable); + ui->AntDescription4->setEnabled(enable); + ui->AntDescription5->setEnabled(enable); + ui->AntDescription6->setEnabled(enable); + ui->AntDescription7->setEnabled(enable); + ui->AntDescription8->setEnabled(enable); + ui->AntDescription9->setEnabled(enable); + ui->AntDescription10->setEnabled(enable); + ui->AntDescription11->setEnabled(enable); + ui->AntDescription12->setEnabled(enable); + ui->AntDescription13->setEnabled(enable); + ui->AntDescription14->setEnabled(enable); + ui->AntDescription15->setEnabled(enable); + ui->AntDescription16->setEnabled(enable); if (enable) - ui.AntDescriptionColumnLabel->setText("Antenna description"); + ui->AntDescriptionColumnLabel->setText("Antenna description"); else - ui.AntDescriptionColumnLabel->setText("Antenna description (enable PSK Reporter)"); + ui->AntDescriptionColumnLabel->setText("Antenna description (enable PSK Reporter)"); } void DevSetup::on_cbPSKReporter_clicked(bool b) @@ -388,48 +392,48 @@ void DevSetup::on_pttMethodComboBox_activated(int index) void DevSetup::on_catPortComboBox_activated(int index) { m_catPortIndex=index; - m_catPort=ui.catPortComboBox->itemText(index); + m_catPort=ui->catPortComboBox->itemText(index); } void DevSetup::on_cbEnableCAT_toggled(bool b) { m_catEnabled=b; enableWidgets(); - ui.cbSplit->setChecked(m_bSplit and m_catEnabled); + ui->cbSplit->setChecked(m_bSplit and m_catEnabled); } void DevSetup::on_serialRateComboBox_activated(int index) { m_serialRateIndex=index; - m_serialRate=ui.serialRateComboBox->itemText(index).toInt(); + m_serialRate=ui->serialRateComboBox->itemText(index).toInt(); } void DevSetup::on_handshakeComboBox_activated(int index) { m_handshakeIndex=index; - m_handshake=ui.handshakeComboBox->itemText(index); + m_handshake=ui->handshakeComboBox->itemText(index); } void DevSetup::on_handshakeComboBox_currentIndexChanged(int index) { - ui.RTSCheckBox->setEnabled(index != 2); + ui->RTSCheckBox->setEnabled(index != 2); } void DevSetup::on_dataBitsComboBox_activated(int index) { m_dataBitsIndex=index; - m_dataBits=ui.dataBitsComboBox->itemText(index).toInt(); + m_dataBits=ui->dataBitsComboBox->itemText(index).toInt(); } void DevSetup::on_stopBitsComboBox_activated(int index) { m_stopBitsIndex=index; - m_stopBits=ui.stopBitsComboBox->itemText(index).toInt(); + m_stopBits=ui->stopBitsComboBox->itemText(index).toInt(); } void DevSetup::on_rigComboBox_activated(int index) { - m_rig = ui.rigComboBox->itemData (index).toInt (); + m_rig = ui->rigComboBox->itemData (index).toInt (); enableWidgets(); } @@ -452,7 +456,7 @@ void DevSetup::on_testCATButton_clicked() int(1000000.0*fMHz)); if(m_poll>0) { m_catEnabled=false; - ui.cbEnableCAT->setChecked(false); + ui->cbEnableCAT->setChecked(false); } } msgBox(t); @@ -492,7 +496,7 @@ void DevSetup::openRig() rig->setConf("stop_bits",buf); rig->setConf("serial_handshake",m_handshake.toLatin1().data()); rig->setConf("dtr_state",m_bDTR ? "ON" : "OFF"); - if(ui.RTSCheckBox->isEnabled()) { + if(ui->RTSCheckBox->isEnabled()) { rig->setConf("rts_state",m_bRTS ? "ON" : "OFF"); } } @@ -504,7 +508,7 @@ void DevSetup::openRig() t="Open rig failed"; msgBox(t); m_catEnabled=false; - ui.cbEnableCAT->setChecked(false); + ui->cbEnableCAT->setChecked(false); return; } } @@ -558,62 +562,117 @@ void DevSetup::on_pttMethodComboBox_currentIndexChanged(int index) { m_pttMethodIndex=index; bool b=m_pttMethodIndex==1 or m_pttMethodIndex==2; - ui.pttComboBox->setEnabled(b); + ui->pttComboBox->setEnabled(b); } void DevSetup::enableWidgets() { - ui.cbEnableCAT->setChecked(m_catEnabled); - ui.rigComboBox->setEnabled(m_catEnabled); - ui.testCATButton->setEnabled(m_catEnabled); - ui.label_4->setEnabled(m_catEnabled); - ui.label_47->setEnabled(m_catEnabled); - ui.cbSplit->setEnabled(m_catEnabled); + ui->cbEnableCAT->setChecked(m_catEnabled); + ui->rigComboBox->setEnabled(m_catEnabled); + ui->testCATButton->setEnabled(m_catEnabled); + ui->label_4->setEnabled(m_catEnabled); + ui->label_47->setEnabled(m_catEnabled); + ui->cbSplit->setEnabled(m_catEnabled); if(m_rig==9999) { //No Split Tx with HRD - ui.cbSplit->setChecked(false); - ui.cbSplit->setEnabled(false); + ui->cbSplit->setChecked(false); + ui->cbSplit->setEnabled(false); } - ui.cbXIT->setEnabled(m_catEnabled); + ui->cbXIT->setEnabled(m_catEnabled); bool bSerial=m_catEnabled and (m_rig<9900); - ui.catPortComboBox->setEnabled(bSerial); - ui.serialRateComboBox->setEnabled(bSerial); - ui.dataBitsComboBox->setEnabled(bSerial); - ui.stopBitsComboBox->setEnabled(bSerial); - ui.handshakeComboBox->setEnabled(bSerial); - ui.DTRCheckBox->setEnabled(bSerial); - ui.DTRCheckBox->setChecked(m_bDTR); - ui.RTSCheckBox->setEnabled(bSerial && m_handshakeIndex != 2); - ui.RTSCheckBox->setChecked(m_bRTS); - ui.rbData->setEnabled(bSerial); - ui.rbMic->setEnabled(bSerial); - ui.label_21->setEnabled(bSerial); - ui.label_22->setEnabled(bSerial); - ui.label_23->setEnabled(bSerial); - ui.label_24->setEnabled(bSerial); - ui.label_25->setEnabled(bSerial); + ui->catPortComboBox->setEnabled(bSerial); + ui->serialRateComboBox->setEnabled(bSerial); + ui->dataBitsComboBox->setEnabled(bSerial); + ui->stopBitsComboBox->setEnabled(bSerial); + ui->handshakeComboBox->setEnabled(bSerial); + ui->DTRCheckBox->setEnabled(bSerial); + ui->DTRCheckBox->setChecked(m_bDTR); + ui->RTSCheckBox->setEnabled(bSerial && m_handshakeIndex != 2); + ui->RTSCheckBox->setChecked(m_bRTS); + ui->rbData->setEnabled(bSerial); + ui->rbMic->setEnabled(bSerial); + ui->label_21->setEnabled(bSerial); + ui->label_22->setEnabled(bSerial); + ui->label_23->setEnabled(bSerial); + ui->label_24->setEnabled(bSerial); + ui->label_25->setEnabled(bSerial); - ui.pollSpinBox->setEnabled(m_catEnabled); + ui->pollSpinBox->setEnabled(m_catEnabled); bool b1=(m_pttMethodIndex==1 or m_pttMethodIndex==2); - ui.pttComboBox->setEnabled(b1); + ui->pttComboBox->setEnabled(b1); b1=b1 and (m_pttPort!=0); bool b2 = (m_catEnabled and m_pttMethodIndex==1 and m_rig<9900) or (m_catEnabled and m_pttMethodIndex==2 and m_rig<9900); bool b3 = (m_catEnabled and m_pttMethodIndex==0); - ui.testPTTButton->setEnabled(b1 or b2 or b3); //Include PTT via HRD or Commander + ui->testPTTButton->setEnabled(b1 or b2 or b3); //Include PTT via HRD or Commander setEnableAntennaDescriptions(m_pskReporter); } void DevSetup::on_cbSplit_toggled(bool checked) { m_bSplit=checked; - if(m_bSplit and m_bXIT) ui.cbXIT->setChecked(false); + if(m_bSplit and m_bXIT) ui->cbXIT->setChecked(false); } void DevSetup::on_cbXIT_toggled(bool checked) { m_bXIT=checked; - if(m_bSplit and m_bXIT) ui.cbSplit->setChecked(false); + if(m_bSplit and m_bXIT) ui->cbSplit->setChecked(false); +} + +void DevSetup::loadAudioDevices (AudioDevices const& d, QComboBox * cb) +{ + using std::copy; + using std::back_inserter; + + int currentIndex = -1; + int defaultIndex = 0; + for (AudioDevices::const_iterator p = d.cbegin (); p != d.cend (); ++p) + { + // convert supported channel counts into something we can store in the item model + QList channelCounts; + QList scc (p->supportedChannelCounts ()); + copy (scc.cbegin (), scc.cend (), back_inserter (channelCounts)); + + cb->addItem (p->deviceName (), channelCounts); + if (*p == m_audioInputDevice) + { + currentIndex = p - d.cbegin (); + } + else if (*p == QAudioDeviceInfo::defaultInputDevice ()) + { + defaultIndex = p - d.cbegin (); + } + } + cb->setCurrentIndex (currentIndex != -1 ? currentIndex : defaultIndex); +} + +void DevSetup::updateAudioChannels (QComboBox const * srcCb, int index, QComboBox * cb, bool allowBoth) +{ + // disable all items + for (int i (0); i < cb->count (); ++i) + { + cb->setItemData (i, 0, Qt::UserRole - 1); // undocumented model internals allows disable + } + + Q_FOREACH (QVariant const& v, srcCb->itemData (index).toList ()) + { + // enable valid options + int n (v.toInt ()); + if (2 == n) + { + cb->setItemData (AudioDevice::Left, 32 | 1, Qt::UserRole - 1); // undocumented model internals allows enable + cb->setItemData (AudioDevice::Right, 32 | 1, Qt::UserRole - 1); + if (allowBoth) + { + cb->setItemData (AudioDevice::Both, 32 | 1, Qt::UserRole - 1); + } + } + else if (1 == n) + { + cb->setItemData (AudioDevice::Mono, 32 | 1, Qt::UserRole - 1); + } + } } typedef QMap RigList; @@ -641,10 +700,10 @@ void DevSetup::enumerateRigs () for (RigList::const_iterator r = rigs.cbegin (); r != rigs.cend (); ++r) { - ui.rigComboBox->addItem (r.key (), r.value ()); + ui->rigComboBox->addItem (r.key (), r.value ()); } - ui.rigComboBox->addItem ("DX Lab Suite Commander", 9998); - ui.rigComboBox->addItem ("Ham Radio Deluxe", 9999); - ui.rigComboBox->setCurrentIndex (ui.rigComboBox->findData (m_rig)); + ui->rigComboBox->addItem ("DX Lab Suite Commander", 9998); + ui->rigComboBox->addItem ("Ham Radio Deluxe", 9999); + ui->rigComboBox->setCurrentIndex (ui->rigComboBox->findData (m_rig)); } diff --git a/devsetup.h b/devsetup.h index 4b9ef5712..51fd2fba0 100644 --- a/devsetup.h +++ b/devsetup.h @@ -1,8 +1,6 @@ #ifndef DEVSETUP_H #define DEVSETUP_H -#include "ui_devsetup.h" - #include #include #include @@ -11,12 +9,23 @@ #include #include "rigclass.h" +#include "AudioDevice.hpp" int rigCallback (rig_caps const *, void *); +namespace Ui { + class DevSetup; +} + +class QComboBox; + class DevSetup : public QDialog { - Q_OBJECT + Q_OBJECT; + + private: + Ui::DevSetup * ui; + public: DevSetup(QWidget *parent=0); ~DevSetup(); @@ -47,6 +56,8 @@ public: QAudioDeviceInfo m_audioOutputDevice; /* selected output device */ bool m_restartSoundIn; bool m_restartSoundOut; + AudioDevice::Channel m_audioInputChannel; + AudioDevice::Channel m_audioOutputChannel; bool m_pskReporter; bool m_firstCall; @@ -99,19 +110,18 @@ private slots: void on_pollSpinBox_valueChanged(int n); void on_pttComboBox_currentIndexChanged(int index); void on_pttMethodComboBox_currentIndexChanged(int index); - void on_cbSplit_toggled(bool checked); - void on_cbXIT_toggled(bool checked); private: + void loadAudioDevices (AudioDevices const&, QComboBox *); + void updateAudioChannels (QComboBox const *, int, QComboBox *, bool); void enumerateRigs (); Rig* rig; void msgBox(QString t); void setEnableAntennaDescriptions(bool enable); void enableWidgets(); void openRig(); - Ui::DialogSndCard ui; friend int rigCallback (rig_caps const *, void *); }; diff --git a/devsetup.ui b/devsetup.ui index c9d4400d5..4310f38ff 100644 --- a/devsetup.ui +++ b/devsetup.ui @@ -1,7 +1,7 @@ - DialogSndCard - + DevSetup + 0 @@ -1137,77 +1137,8 @@ - - - - - - - - 90 - 0 - - - - - 90 - 16777215 - - - - Audio In: - - - - - - - true - - - Select audio input device and driver API - - - - - - - - - - - - 0 - 0 - - - - - 90 - 0 - - - - - 90 - 16777215 - - - - Audio Out: - - - - - - - select audio output device and driver API - - - - - - + + @@ -1240,6 +1171,136 @@ + + + + + + + 90 + 0 + + + + + 90 + 16777215 + + + + Audio In: + + + + + + + true + + + + 0 + 0 + + + + Select audio input device and driver API + + + + + + + + Mono + + + + + Left + + + + + Right + + + + + + + + + + + + + 0 + 0 + + + + + 90 + 0 + + + + + 90 + 16777215 + + + + Audio Out: + + + + + + + + 0 + 0 + + + + select audio output device and driver API + + + + + + + + 0 + 0 + + + + + Mono + + + + + Left + + + + + Right + + + + + Both + + + + + + @@ -1807,7 +1868,7 @@ 0 0 - 510 + 308 449 @@ -2519,7 +2580,7 @@ buttonBox accepted() - DialogSndCard + DevSetup accept() @@ -2535,7 +2596,7 @@ buttonBox rejected() - DialogSndCard + DevSetup reject() diff --git a/killbyname.cpp b/killbyname.cpp index 240ad5aca..3fe8841e2 100644 --- a/killbyname.cpp +++ b/killbyname.cpp @@ -1,284 +1,284 @@ -#include -#include -#include - -int killbyname(const char *szToTerminate) -// Created: 6/23/2000 (Ravi Kochhar) -// Last modified: 3/10/2002 (RK) -// Please report any problems or bugs to kochhar@physiology.wisc.edu -// The latest version of this routine can be found at: -// http://www.neurophys.wisc.edu/ravi/software/killproc/ -// Terminate the process "szToTerminate" if it is currently running -// This works for Win/95/98/ME and also Win/NT/2000/XP -// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE" -// will both work (for szToTerminate) -// Return codes are as follows: -// 0 = Process was successfully terminated -// 602 = Unable to terminate process for some other reason -// 603 = Process was not currently running -// 604 = No permission to terminate process -// 605 = Unable to load PSAPI.DLL -// 606 = Unable to identify system type -// 607 = Unsupported OS -// 632 = Invalid process name -// 700 = Unable to get procedure address from PSAPI.DLL -// 701 = Unable to get process list, EnumProcesses failed -// 702 = Unable to load KERNEL32.DLL -// 703 = Unable to get procedure address from KERNEL32.DLL -// 704 = CreateToolhelp32Snapshot failed - -{ - BOOL bResult,bResultm; - DWORD aiPID[1000],iCb=1000,iNumProc; //,iV2000=0; - DWORD iCbneeded,i,iFound=0; - char szName[MAX_PATH],szToTermUpper[MAX_PATH]; - HANDLE hProc,hSnapShot,hSnapShotm; - OSVERSIONINFO osvi; - HINSTANCE hInstLib; -// int iLen,iLenP,indx; - int iLenP,indx; - HMODULE hMod; - PROCESSENTRY32 procentry; - MODULEENTRY32 modentry; - - // Transfer Process name into "szToTermUpper" and convert to upper case - iLenP=strlen(szToTerminate); - if(iLenP<1 || iLenP>MAX_PATH) return 632; - for(indx=0;indx +#include +#include + +int killbyname(const char *szToTerminate) +// Created: 6/23/2000 (Ravi Kochhar) +// Last modified: 3/10/2002 (RK) +// Please report any problems or bugs to kochhar@physiology.wisc.edu +// The latest version of this routine can be found at: +// http://www.neurophys.wisc.edu/ravi/software/killproc/ +// Terminate the process "szToTerminate" if it is currently running +// This works for Win/95/98/ME and also Win/NT/2000/XP +// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE" +// will both work (for szToTerminate) +// Return codes are as follows: +// 0 = Process was successfully terminated +// 602 = Unable to terminate process for some other reason +// 603 = Process was not currently running +// 604 = No permission to terminate process +// 605 = Unable to load PSAPI.DLL +// 606 = Unable to identify system type +// 607 = Unsupported OS +// 632 = Invalid process name +// 700 = Unable to get procedure address from PSAPI.DLL +// 701 = Unable to get process list, EnumProcesses failed +// 702 = Unable to load KERNEL32.DLL +// 703 = Unable to get procedure address from KERNEL32.DLL +// 704 = CreateToolhelp32Snapshot failed + +{ + BOOL bResult,bResultm; + DWORD aiPID[1000],iCb=1000,iNumProc; //,iV2000=0; + DWORD iCbneeded,i,iFound=0; + char szName[MAX_PATH],szToTermUpper[MAX_PATH]; + HANDLE hProc,hSnapShot,hSnapShotm; + OSVERSIONINFO osvi; + HINSTANCE hInstLib; +// int iLen,iLenP,indx; + int iLenP,indx; + HMODULE hMod; + PROCESSENTRY32 procentry; + MODULEENTRY32 modentry; + + // Transfer Process name into "szToTermUpper" and convert to upper case + iLenP=strlen(szToTerminate); + if(iLenP<1 || iLenP>MAX_PATH) return 632; + for(indx=0;indx a(1:3) - - complex cx(npts) - real a(5),deltaa(5) - - a(1)=0. - a(2)=0. - a(3)=0. - a(4)=0. - deltaa(1)=2.0 - deltaa(2)=2.0 - deltaa(3)=2.0 - deltaa(4)=0.05 - nterms=3 !Maybe 2 is enough? - -! Start the iteration - chisqr=0. - chisqr0=1.e6 - do iter=1,3 !One iteration is enough? - do j=1,nterms - chisq1=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) - fn=0. - delta=deltaa(j) -10 a(j)=a(j)+delta - chisq2=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) - if(chisq2.eq.chisq1) go to 10 - if(chisq2.gt.chisq1) then - delta=-delta !Reverse direction - a(j)=a(j)+delta - tmp=chisq1 - chisq1=chisq2 - chisq2=tmp - endif -20 fn=fn+1.0 - a(j)=a(j)+delta - chisq3=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) - if(chisq3.lt.chisq2) then - chisq1=chisq2 - chisq2=chisq3 - go to 20 - endif - -! Find minimum of parabola defined by last three points - delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5) - a(j)=a(j)-delta - deltaa(j)=deltaa(j)*fn/3. - enddo - chisqr=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) - if(chisqr/chisqr0.gt.0.9999) go to 30 - chisqr0=chisqr - enddo - -30 ccfbest=ccfmax * (1378.125/fsample)**2 - dtbest=dtmax - - return -end subroutine afc65b +subroutine afc65b(cx,npts,fsample,nflip,a,ccfbest,dtbest) + +! Find delta f, f1, f2 ==> a(1:3) + + complex cx(npts) + real a(5),deltaa(5) + + a(1)=0. + a(2)=0. + a(3)=0. + a(4)=0. + deltaa(1)=2.0 + deltaa(2)=2.0 + deltaa(3)=2.0 + deltaa(4)=0.05 + nterms=3 !Maybe 2 is enough? + +! Start the iteration + chisqr=0. + chisqr0=1.e6 + do iter=1,3 !One iteration is enough? + do j=1,nterms + chisq1=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + fn=0. + delta=deltaa(j) +10 a(j)=a(j)+delta + chisq2=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + if(chisq2.eq.chisq1) go to 10 + if(chisq2.gt.chisq1) then + delta=-delta !Reverse direction + a(j)=a(j)+delta + tmp=chisq1 + chisq1=chisq2 + chisq2=tmp + endif +20 fn=fn+1.0 + a(j)=a(j)+delta + chisq3=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + if(chisq3.lt.chisq2) then + chisq1=chisq2 + chisq2=chisq3 + go to 20 + endif + +! Find minimum of parabola defined by last three points + delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5) + a(j)=a(j)-delta + deltaa(j)=deltaa(j)*fn/3. + enddo + chisqr=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + if(chisqr/chisqr0.gt.0.9999) go to 30 + chisqr0=chisqr + enddo + +30 ccfbest=ccfmax * (1378.125/fsample)**2 + dtbest=dtmax + + return +end subroutine afc65b diff --git a/lib/afc9.f90 b/lib/afc9.f90 index 1fbcf2fa3..5b4546cf0 100644 --- a/lib/afc9.f90 +++ b/lib/afc9.f90 @@ -1,58 +1,58 @@ -subroutine afc9(c3,npts,fsample,a,syncpk) - - complex c3(0:npts-1) - real a(3),deltaa(3) - - a(1)=0. !f0 - a(2)=0. !f1 - a(3)=0. !f2 - deltaa(1)=0.2 - deltaa(2)=0.01 - deltaa(3)=0.01 - nterms=3 - -! Start the iteration - chisqr=0. - chisqr0=1.e6 - do iter=1,4 !One iteration is enough? - do j=1,nterms - chisq1=fchisq(c3,npts,fsample,a) - fn=0. - delta=deltaa(j) -10 a(j)=a(j)+delta - chisq2=fchisq(c3,npts,fsample,a) - if(chisq2.eq.chisq1) go to 10 - if(chisq2.gt.chisq1) then - delta=-delta !Reverse direction - a(j)=a(j)+delta - tmp=chisq1 - chisq1=chisq2 - chisq2=tmp - endif -20 fn=fn+1.0 - a(j)=a(j)+delta - chisq3=fchisq(c3,npts,fsample,a) - if(chisq3.lt.chisq2) then - chisq1=chisq2 - chisq2=chisq3 - go to 20 - endif - -! Find minimum of parabola defined by last three points - delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5) - a(j)=a(j)-delta - deltaa(j)=deltaa(j)*fn/3. -! write(*,4000) iter,j,a,deltaa,-chisq2 -!4000 format(i1,i2,6f10.4,f9.3) - enddo - chisqr=fchisq(c3,npts,fsample,a) - if(chisqr/chisqr0.gt.0.9999) exit - chisqr0=chisqr - enddo - - syncpk=-chisqr -! write(*,4001) a,deltaa,-chisq2 -!4001 format(3x,6f10.4,f9.3) - - return -end subroutine afc9 +subroutine afc9(c3,npts,fsample,a,syncpk) + + complex c3(0:npts-1) + real a(3),deltaa(3) + + a(1)=0. !f0 + a(2)=0. !f1 + a(3)=0. !f2 + deltaa(1)=0.2 + deltaa(2)=0.01 + deltaa(3)=0.01 + nterms=3 + +! Start the iteration + chisqr=0. + chisqr0=1.e6 + do iter=1,4 !One iteration is enough? + do j=1,nterms + chisq1=fchisq(c3,npts,fsample,a) + fn=0. + delta=deltaa(j) +10 a(j)=a(j)+delta + chisq2=fchisq(c3,npts,fsample,a) + if(chisq2.eq.chisq1) go to 10 + if(chisq2.gt.chisq1) then + delta=-delta !Reverse direction + a(j)=a(j)+delta + tmp=chisq1 + chisq1=chisq2 + chisq2=tmp + endif +20 fn=fn+1.0 + a(j)=a(j)+delta + chisq3=fchisq(c3,npts,fsample,a) + if(chisq3.lt.chisq2) then + chisq1=chisq2 + chisq2=chisq3 + go to 20 + endif + +! Find minimum of parabola defined by last three points + delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5) + a(j)=a(j)-delta + deltaa(j)=deltaa(j)*fn/3. +! write(*,4000) iter,j,a,deltaa,-chisq2 +!4000 format(i1,i2,6f10.4,f9.3) + enddo + chisqr=fchisq(c3,npts,fsample,a) + if(chisqr/chisqr0.gt.0.9999) exit + chisqr0=chisqr + enddo + + syncpk=-chisqr +! write(*,4001) a,deltaa,-chisq2 +!4001 format(3x,6f10.4,f9.3) + + return +end subroutine afc9 diff --git a/lib/gran.c b/lib/gran.c index ceeb6da7d..24b986503 100644 --- a/lib/gran.c +++ b/lib/gran.c @@ -1,28 +1,28 @@ -#include -#include - -/* Generate gaussian random float with mean=0 and std_dev=1 */ -float gran_() -{ - float fac,rsq,v1,v2; - static float gset; - static int iset; - - if(iset){ - /* Already got one */ - iset = 0; - return gset; - } - /* Generate two evenly distributed numbers between -1 and +1 - * that are inside the unit circle - */ - do { - v1 = 2.0 * (float)rand() / RAND_MAX - 1; - v2 = 2.0 * (float)rand() / RAND_MAX - 1; - rsq = v1*v1 + v2*v2; - } while(rsq >= 1.0 || rsq == 0.0); - fac = sqrt(-2.0*log(rsq)/rsq); - gset = v1*fac; - iset++; - return v2*fac; -} +#include +#include + +/* Generate gaussian random float with mean=0 and std_dev=1 */ +float gran_() +{ + float fac,rsq,v1,v2; + static float gset; + static int iset; + + if(iset){ + /* Already got one */ + iset = 0; + return gset; + } + /* Generate two evenly distributed numbers between -1 and +1 + * that are inside the unit circle + */ + do { + v1 = 2.0 * (float)rand() / RAND_MAX - 1; + v2 = 2.0 * (float)rand() / RAND_MAX - 1; + rsq = v1*v1 + v2*v2; + } while(rsq >= 1.0 || rsq == 0.0); + fac = sqrt(-2.0*log(rsq)/rsq); + gset = v1*fac; + iset++; + return v2*fac; +} diff --git a/lib/usleep.c b/lib/usleep.c index df01f92e0..cdaa7f909 100644 --- a/lib/usleep.c +++ b/lib/usleep.c @@ -1,5 +1,5 @@ -/* usleep(3) */ -void usleep_(unsigned long *microsec) -{ - usleep(*microsec); -} +/* usleep(3) */ +void usleep_(unsigned long *microsec) +{ + usleep(*microsec); +} diff --git a/lib/wrapkarn.c b/lib/wrapkarn.c index 1b1a6311f..9e0a51caf 100644 --- a/lib/wrapkarn.c +++ b/lib/wrapkarn.c @@ -1,70 +1,70 @@ -#include -#include -#include -#include -#include -#include "rs.h" - -static void *rs; -static int first=1; - -void rs_encode_(int *dgen, int *sent) -// Encode JT65 data dgen[12], producing sent[63]. -{ - int dat1[12]; - int b[51]; - int i; - - if(first) { - // Initialize the JT65 codec - rs=init_rs_int(6,0x43,3,1,51,0); - first=0; - } - - // Reverse data order for the Karn codec. - for(i=0; i<12; i++) { - dat1[i]=dgen[11-i]; - } - // Compute the parity symbols - encode_rs_int(rs,dat1,b); - - // Move parity symbols and data into sent[] array, in reverse order. - for (i = 0; i < 51; i++) sent[50-i] = b[i]; - for (i = 0; i < 12; i++) sent[i+51] = dat1[11-i]; -} - -void rs_decode_(int *recd0, int *era0, int *numera0, int *decoded, int *nerr) -// Decode JT65 received data recd0[63], producing decoded[12]. -// Erasures are indicated in era0[numera]. The number of corrected -// errors is *nerr. If the data are uncorrectable, *nerr=-1 is returned. -{ - int numera; - int i; - int era_pos[50]; - int recd[63]; - - if(first) { - rs=init_rs_int(6,0x43,3,1,51,0); - first=0; - } - - numera=*numera0; - for(i=0; i<12; i++) recd[i]=recd0[62-i]; - for(i=0; i<51; i++) recd[12+i]=recd0[50-i]; - if(numera) - for(i=0; i +#include +#include +#include +#include +#include "rs.h" + +static void *rs; +static int first=1; + +void rs_encode_(int *dgen, int *sent) +// Encode JT65 data dgen[12], producing sent[63]. +{ + int dat1[12]; + int b[51]; + int i; + + if(first) { + // Initialize the JT65 codec + rs=init_rs_int(6,0x43,3,1,51,0); + first=0; + } + + // Reverse data order for the Karn codec. + for(i=0; i<12; i++) { + dat1[i]=dgen[11-i]; + } + // Compute the parity symbols + encode_rs_int(rs,dat1,b); + + // Move parity symbols and data into sent[] array, in reverse order. + for (i = 0; i < 51; i++) sent[50-i] = b[i]; + for (i = 0; i < 12; i++) sent[i+51] = dat1[11-i]; +} + +void rs_decode_(int *recd0, int *era0, int *numera0, int *decoded, int *nerr) +// Decode JT65 received data recd0[63], producing decoded[12]. +// Erasures are indicated in era0[numera]. The number of corrected +// errors is *nerr. If the data are uncorrectable, *nerr=-1 is returned. +{ + int numera; + int i; + int era_pos[50]; + int recd[63]; + + if(first) { + rs=init_rs_int(6,0x43,3,1,51,0); + first=0; + } + + numera=*numera0; + for(i=0; i<12; i++) recd[i]=recd0[62-i]; + for(i=0; i<51; i++) recd[12+i]=recd0[50-i]; + if(numera) + for(i=0; i -#include - - -LogQSO::LogQSO(QWidget *parent) : - QDialog(parent), - ui(new Ui::LogQSO) -{ - ui->setupUi(this); -} - -LogQSO::~LogQSO() -{ - delete ui; -} - -void LogQSO::initLogQSO(QString hisCall, QString hisGrid, QString mode, - QString rptSent, QString rptRcvd, QDateTime dateTime, - double dialFreq, QString myCall, QString myGrid, - bool noSuffix, bool toRTTY, bool dBtoComments) -{ - ui->call->setText(hisCall); - ui->grid->setText(hisGrid); - ui->txPower->setText(""); - ui->comments->setText(""); - if(m_saveTxPower) ui->txPower->setText(m_txPower); - if(m_saveComments) ui->comments->setText(m_comments); - if(dBtoComments) { - QString t=mode; - if(rptSent!="") t+=" Sent: " + rptSent; - if(rptRcvd!="") t+=" Rcvd: " + rptRcvd; - ui->comments->setText(t); - } - if(noSuffix and mode.mid(0,3)=="JT9") mode="JT9"; - if(toRTTY and mode.mid(0,3)=="JT9") mode="RTTY"; - ui->mode->setText(mode); - ui->sent->setText(rptSent); - ui->rcvd->setText(rptRcvd); - m_dateTime=dateTime; - QString date=dateTime.toString("yyyy-MM-dd"); - ui->date->setText(date); - QString time=dateTime.toString("hhmm"); - ui->time->setText(time); - m_dialFreq=dialFreq; - m_myCall=myCall; - m_myGrid=myGrid; - QString band=""; - if(dialFreq>0.135 and dialFreq<0.139) band="2200m"; - if(dialFreq>0.45 and dialFreq<0.55) band="630m"; - if(dialFreq>1.8 and dialFreq<2.0) band="160m"; - if(dialFreq>3.5 and dialFreq<4.0) band="80m"; - if(dialFreq>5.1 and dialFreq<5.45) band="60m"; - if(dialFreq>7.0 and dialFreq<7.3) band="40m"; - if(dialFreq>10.0 and dialFreq<10.15) band="30m"; - if(dialFreq>14.0 and dialFreq<14.35) band="20m"; - if(dialFreq>18.068 and dialFreq<18.168) band="17m"; - if(dialFreq>21.0 and dialFreq<21.45) band="15m"; - if(dialFreq>24.890 and dialFreq<24.990) band="12m"; - if(dialFreq>28.0 and dialFreq<29.7) band="10m"; - if(dialFreq>50.0 and dialFreq<54.0) band="6m"; - if(dialFreq>70.0 and dialFreq<71.0) band="4m"; - if(dialFreq>144.0 and dialFreq<148.0) band="2m"; - if(dialFreq>222.0 and dialFreq<225.0) band="1.25m"; - if(dialFreq>420.0 and dialFreq<450.0) band="70cm"; - if(dialFreq>902.0 and dialFreq<928.0) band="33cm"; - if(dialFreq>1240.0 and dialFreq<1300.0) band="23cm"; - if(dialFreq>2300.0 and dialFreq<2450.0) band="13cm"; - if(dialFreq>3300.0 and dialFreq<3500.0) band="9cm"; - if(dialFreq>5650.0 and dialFreq<5925.0) band="6cm"; - if(dialFreq>10000.0 and dialFreq<10500.0) band="3cm"; - if(dialFreq>24000.0 and dialFreq<24250.0) band="1.25cm"; - if(dialFreq>47000.0 and dialFreq<47200.0) band="6mm"; - if(dialFreq>75500.0 and dialFreq<81000.0) band="4mm"; - ui->band->setText(band); - ui->cbTxPower->setChecked(m_saveTxPower); - ui->cbComments->setChecked(m_saveComments); -} - -void LogQSO::accept() -{ - QString hisCall,hisGrid,mode,rptSent,rptRcvd,date,time,band; - QString comments,name; - - hisCall=ui->call->text(); - hisGrid=ui->grid->text(); - mode=ui->mode->text(); - rptSent=ui->sent->text(); - rptRcvd=ui->rcvd->text(); - date=ui->date->text(); - date=date.mid(0,4) + date.mid(5,2) + date.mid(8,2); - time=ui->time->text(); - band=ui->band->text(); - name=ui->name->text(); - m_txPower=ui->txPower->text(); - comments=ui->comments->text(); - m_comments=comments; - QString strDialFreq(QString::number(m_dialFreq,'f',6)); - -//Log this QSO to file "wsjtx_log.adi" - QFile f2("wsjtx_log.adi"); - if(!f2.open(QIODevice::Text | QIODevice::Append)) { - QMessageBox m; - m.setText("Cannot open file \"wsjtx_log.adi\"."); - m.exec(); - } else { - QTextStream out(&f2); - if(f2.size()==0) out << "WSJT-X ADIF Export" << endl; - - QString t; - t="" + hisCall; - t+=" " + hisGrid; - t+=" " + mode; - t+=" " + rptSent; - t+=" " + rptRcvd; - t+=" " + date; - t+=" " + time; - t+=" " + band; - t+=" " + strDialFreq; - t+=" " + - m_myCall; - t+=" " + - m_myGrid; - if(m_txPower!="") t+= " " + m_txPower; - if(comments!="") t+=" " + comments; - if(name!="") t+=" " + name; - t+=" "; - out << t << endl; - f2.close(); - } - -//Log this QSO to file "wsjtx.log" - QFile f("wsjtx.log"); - if(!f.open(QIODevice::Text | QIODevice::Append)) { - QMessageBox m; - m.setText("Cannot open file \"wsjtx.log\"."); - m.exec(); - } else { - QString logEntry=m_dateTime.date().toString("yyyy-MMM-dd,") + - m_dateTime.time().toString("hh:mm,") + hisCall + "," + - hisGrid + "," + strDialFreq + "," + mode + - "," + rptSent + "," + rptRcvd; - if(m_txPower!="") logEntry += "," + m_txPower; - if(comments!="") logEntry += "," + comments; - if(name!="") logEntry += "," + name; - QTextStream out(&f); - out << logEntry << endl; - f.close(); - } - -//Clean up and finish logging - emit(acceptQSO(true)); - QDialog::accept(); -} - -void LogQSO::reject() -{ - emit(acceptQSO(false)); - QDialog::reject(); -} - -void LogQSO::on_cbTxPower_toggled(bool checked) -{ - m_saveTxPower=checked; -} - -void LogQSO::on_cbComments_toggled(bool checked) -{ - m_saveComments=checked; -} +#include "logqso.h" +#include "ui_logqso.h" +#include +#include + + +LogQSO::LogQSO(QSettings * settings, QWidget *parent) : + QDialog(parent), + ui(new Ui::LogQSO), + m_settings (settings) +{ + ui->setupUi(this); + + loadSettings (); +} + +LogQSO::~LogQSO () +{ +} + +void LogQSO::loadSettings () +{ + m_settings->beginGroup ("LogQSO"); + restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ()); + ui->cbTxPower->setChecked (m_settings->value ("SaveTxPower", false).toBool ()); + ui->cbComments->setChecked (m_settings->value ("SaveComments", false).toBool ()); + m_txPower = m_settings->value ("TxPower", "").toString (); + m_comments = m_settings->value ("LogComments", "").toString(); + m_settings->endGroup (); +} + +void LogQSO::storeSettings () const +{ + m_settings->beginGroup ("LogQSO"); + m_settings->setValue ("geometry", saveGeometry ()); + m_settings->setValue ("SaveTxPower", ui->cbTxPower->isChecked ()); + m_settings->setValue ("SaveComments", ui->cbComments->isChecked ()); + m_settings->setValue ("TxPower", m_txPower); + m_settings->setValue ("LogComments", m_comments); + m_settings->endGroup (); +} + +void LogQSO::initLogQSO(QString hisCall, QString hisGrid, QString mode, + QString rptSent, QString rptRcvd, QDateTime dateTime, + double dialFreq, QString myCall, QString myGrid, + bool noSuffix, bool toRTTY, bool dBtoComments) +{ + ui->call->setText(hisCall); + ui->grid->setText(hisGrid); + ui->txPower->setText(""); + ui->comments->setText(""); + if (ui->cbTxPower->isChecked ()) ui->txPower->setText(m_txPower); + if (ui->cbComments->isChecked ()) ui->comments->setText(m_comments); + if(dBtoComments) { + QString t=mode; + if(rptSent!="") t+=" Sent: " + rptSent; + if(rptRcvd!="") t+=" Rcvd: " + rptRcvd; + ui->comments->setText(t); + } + if(noSuffix and mode.mid(0,3)=="JT9") mode="JT9"; + if(toRTTY and mode.mid(0,3)=="JT9") mode="RTTY"; + ui->mode->setText(mode); + ui->sent->setText(rptSent); + ui->rcvd->setText(rptRcvd); + m_dateTime=dateTime; + QString date=dateTime.toString("yyyy-MM-dd"); + ui->date->setText(date); + QString time=dateTime.toString("hhmm"); + ui->time->setText(time); + m_dialFreq=dialFreq; + m_myCall=myCall; + m_myGrid=myGrid; + QString band=""; + if(dialFreq>0.135 and dialFreq<0.139) band="2200m"; + if(dialFreq>0.45 and dialFreq<0.55) band="630m"; + if(dialFreq>1.8 and dialFreq<2.0) band="160m"; + if(dialFreq>3.5 and dialFreq<4.0) band="80m"; + if(dialFreq>5.1 and dialFreq<5.45) band="60m"; + if(dialFreq>7.0 and dialFreq<7.3) band="40m"; + if(dialFreq>10.0 and dialFreq<10.15) band="30m"; + if(dialFreq>14.0 and dialFreq<14.35) band="20m"; + if(dialFreq>18.068 and dialFreq<18.168) band="17m"; + if(dialFreq>21.0 and dialFreq<21.45) band="15m"; + if(dialFreq>24.890 and dialFreq<24.990) band="12m"; + if(dialFreq>28.0 and dialFreq<29.7) band="10m"; + if(dialFreq>50.0 and dialFreq<54.0) band="6m"; + if(dialFreq>70.0 and dialFreq<71.0) band="4m"; + if(dialFreq>144.0 and dialFreq<148.0) band="2m"; + if(dialFreq>222.0 and dialFreq<225.0) band="1.25m"; + if(dialFreq>420.0 and dialFreq<450.0) band="70cm"; + if(dialFreq>902.0 and dialFreq<928.0) band="33cm"; + if(dialFreq>1240.0 and dialFreq<1300.0) band="23cm"; + if(dialFreq>2300.0 and dialFreq<2450.0) band="13cm"; + if(dialFreq>3300.0 and dialFreq<3500.0) band="9cm"; + if(dialFreq>5650.0 and dialFreq<5925.0) band="6cm"; + if(dialFreq>10000.0 and dialFreq<10500.0) band="3cm"; + if(dialFreq>24000.0 and dialFreq<24250.0) band="1.25cm"; + if(dialFreq>47000.0 and dialFreq<47200.0) band="6mm"; + if(dialFreq>75500.0 and dialFreq<81000.0) band="4mm"; + ui->band->setText(band); + + show (); +} + +void LogQSO::accept() +{ + QString hisCall,hisGrid,mode,rptSent,rptRcvd,date,time,band; + QString comments,name; + + hisCall=ui->call->text(); + hisGrid=ui->grid->text(); + mode=ui->mode->text(); + rptSent=ui->sent->text(); + rptRcvd=ui->rcvd->text(); + date=ui->date->text(); + date=date.mid(0,4) + date.mid(5,2) + date.mid(8,2); + time=ui->time->text(); + band=ui->band->text(); + name=ui->name->text(); + m_txPower=ui->txPower->text(); + comments=ui->comments->text(); + m_comments=comments; + QString strDialFreq(QString::number(m_dialFreq,'f',6)); + +//Log this QSO to file "wsjtx_log.adi" + QFile f2("wsjtx_log.adi"); + if(!f2.open(QIODevice::Text | QIODevice::Append)) { + QMessageBox m; + m.setText("Cannot open file \"wsjtx_log.adi\"."); + m.exec(); + } else { + QTextStream out(&f2); + if(f2.size()==0) out << "WSJT-X ADIF Export" << endl; + + QString t; + t="" + hisCall; + t+=" " + hisGrid; + t+=" " + mode; + t+=" " + rptSent; + t+=" " + rptRcvd; + t+=" " + date; + t+=" " + time; + t+=" " + band; + t+=" " + strDialFreq; + t+=" " + + m_myCall; + t+=" " + + m_myGrid; + if(m_txPower!="") t+= " " + m_txPower; + if(comments!="") t+=" " + comments; + if(name!="") t+=" " + name; + t+=" "; + out << t << endl; + f2.close(); + } + +//Log this QSO to file "wsjtx.log" + QFile f("wsjtx.log"); + if(!f.open(QIODevice::Text | QIODevice::Append)) { + QMessageBox m; + m.setText("Cannot open file \"wsjtx.log\"."); + m.exec(); + } else { + QString logEntry=m_dateTime.date().toString("yyyy-MMM-dd,") + + m_dateTime.time().toString("hh:mm,") + hisCall + "," + + hisGrid + "," + strDialFreq + "," + mode + + "," + rptSent + "," + rptRcvd; + if(m_txPower!="") logEntry += "," + m_txPower; + if(comments!="") logEntry += "," + comments; + if(name!="") logEntry += "," + name; + QTextStream out(&f); + out << logEntry << endl; + f.close(); + } + +//Clean up and finish logging + emit(acceptQSO(true)); + QDialog::accept(); +} + +void LogQSO::reject() +{ + emit(acceptQSO(false)); + QDialog::reject(); +} + +// closeEvent is only called from the system menu close widget for a +// modeless dialog so we use the hideEvent override to store the +// window settings +void LogQSO::hideEvent (QHideEvent * e) +{ + storeSettings (); + QDialog::hideEvent (e); +} diff --git a/logqso.h b/logqso.h index 06b2edfc9..a0c1a7b7c 100644 --- a/logqso.h +++ b/logqso.h @@ -1,53 +1,54 @@ -#ifndef LogQSO_H -#define LogQSO_H - -#ifdef QT5 -#include -#else -#include -#endif - -namespace Ui { -class LogQSO; -} - -class LogQSO : public QDialog -{ - Q_OBJECT - -public: - explicit LogQSO(QWidget *parent = 0); - ~LogQSO(); - void initLogQSO(QString hisCall, QString hisGrid, QString mode, - QString rptSent, QString rptRcvd, QDateTime dateTime, - double dialFreq, QString myCall, QString myGrid, - bool noSuffix, bool toRTTY, bool dBtoComments); - - double m_dialFreq; - - bool m_saveTxPower; - bool m_saveComments; - - QString m_myCall; - QString m_myGrid; - QString m_txPower; - QString m_comments; - - QDateTime m_dateTime; - -public slots: - void accept(); - void reject(); - -signals: - void acceptQSO(bool accepted); - -private slots: - void on_cbTxPower_toggled(bool checked); - void on_cbComments_toggled(bool checked); - -private: - Ui::LogQSO *ui; -}; - -#endif // LogQSO_H +#ifndef LogQSO_H +#define LogQSO_H + +#ifdef QT5 +#include +#else +#include +#endif + +#include + +namespace Ui { + class LogQSO; +} + +class QSettings; + +class LogQSO : public QDialog +{ + Q_OBJECT + +public: + explicit LogQSO(QSettings *, QWidget *parent = 0); + ~LogQSO(); + void initLogQSO(QString hisCall, QString hisGrid, QString mode, + QString rptSent, QString rptRcvd, QDateTime dateTime, + double dialFreq, QString myCall, QString myGrid, + bool noSuffix, bool toRTTY, bool dBtoComments); + +public slots: + void accept(); + void reject(); + +signals: + void acceptQSO(bool accepted); + +protected: + void hideEvent (QHideEvent *); + +private: + void loadSettings (); + void storeSettings () const; + + QScopedPointer ui; + QSettings * m_settings; + QString m_txPower; + QString m_comments; + double m_dialFreq; + QString m_myCall; + QString m_myGrid; + QDateTime m_dateTime; +}; + +#endif // LogQSO_H diff --git a/main.cpp b/main.cpp index 7d40fe2e4..c52f259c7 100644 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,7 @@ #endif #include #include +#include #include "mainwindow.h" @@ -18,6 +19,10 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); + qRegisterMetaType ("AudioDevice::Channel"); + + QSettings settings(a.applicationDirPath() + "/wsjtx.ini", QSettings::IniFormat); + QFile f("fonts.txt"); qint32 fontSize,fontWeight,fontSize2,fontWeight2; // Defaults 8 50 10 50 fontSize2=10; @@ -51,7 +56,7 @@ int main(int argc, char *argv[]) memset(to,0,size); //Zero all decoding params in shared memory // Multiple instances: Call MainWindow() with the UUID key - MainWindow w(&mem_jt9, &my_key, fontSize2, fontWeight2); + MainWindow w(&settings, &mem_jt9, &my_key, fontSize2, fontWeight2); w.show(); QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit())); diff --git a/mainwindow.cpp b/mainwindow.cpp index 652db5601..7fcfc914e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -15,7 +15,6 @@ #include "logqso.h" #ifdef QT5 -#include #include #endif @@ -30,8 +29,6 @@ static int nc1=1; wchar_t buffer[256]; -WideGraph* g_pWideGraph = NULL; -LogQSO* logDlg = NULL; Rig* rig = NULL; QTextEdit* pShortcuts; QTcpSocket* commanderSocket = new QTcpSocket(0); @@ -42,49 +39,73 @@ QString Program_Title_Version=" WSJT-X v1.2, r" + rev.mid(6,4) + //-------------------------------------------------- MainWindow constructor // Multiple instances: new arg *thekey -MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, \ - qint32 fontSize2, qint32 fontWeight2, \ +MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *thekey, + qint32 fontSize2, qint32 fontWeight2, QWidget *parent) : QMainWindow(parent), + m_settings (settings), ui(new Ui::MainWindow), - m_detector (RX_SAMPLE_RATE, NTMAX / 2, 6912 / 2 * sizeof (jt9com_.d2[0]), this), + m_wideGraph (new WideGraph (settings)), + m_logDlg (new LogQSO (settings, this)), + m_detector (RX_SAMPLE_RATE, NTMAX / 2, 6912 / 2, this), m_audioInputDevice (QAudioDeviceInfo::defaultInputDevice ()), // start with default m_modulator (TX_SAMPLE_RATE, NTMAX / 2), m_audioOutputDevice (QAudioDeviceInfo::defaultOutputDevice ()), // start with default m_soundOutput (&m_modulator) { ui->setupUi(this); - m_detector.open (); - m_modulator.open (); connect (this, &MainWindow::finished, this, &MainWindow::close); // start sound out thread and hook up slots & signals for shutdown management + + // these two objects need to be in the other thread so that invoking + // their slots is done in a thread safe way m_soundOutput.moveToThread (&m_soundOutputThread); + m_modulator.moveToThread (&m_soundOutputThread); + connect (this, &MainWindow::finished, &m_soundOutputThread, &QThread::quit); // quit thread event loop connect (&m_soundOutputThread, &QThread::finished, &m_soundOutputThread, &QThread::deleteLater); // disposal // hook up sound output stream slots & signals - connect (this, &MainWindow::startAudioOutputStream, &m_soundOutput, &SoundOutput::startStream); - connect (this, &MainWindow::stopAudioOutputStream, &m_soundOutput, &SoundOutput::stopStream); + connect (this, SIGNAL (startAudioOutputStream (QAudioDeviceInfo const&, unsigned)), &m_soundOutput, SLOT (startStream (QAudioDeviceInfo const&, unsigned))); + connect (this, SIGNAL (stopAudioOutputStream ()), &m_soundOutput, SLOT (stopStream ())); connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError); // connect (&m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage); + connect (this, SIGNAL (outAttenuationChanged (qreal)), &m_soundOutput, SLOT (setAttenuation (qreal))); // hook up Modulator slots - connect (this, &MainWindow::muteAudioOutput, &m_modulator, &Modulator::mute); - connect (this, &MainWindow::transmitFrequency, &m_modulator, &Modulator::setFrequency); - connect (this, &MainWindow::endTransmitMessage, &m_modulator, &Modulator::stop); - connect (this, &MainWindow::tune, &m_modulator, &Modulator::tune); + connect (this, SIGNAL (muteAudioOutput (bool)), &m_modulator, SLOT (mute (bool))); + connect (this, SIGNAL(transmitFrequency (unsigned)), &m_modulator, SLOT (setFrequency (unsigned))); + connect (this, SIGNAL (endTransmitMessage ()), &m_modulator, SLOT (close ())); + connect (this, SIGNAL (tune (bool)), &m_modulator, SLOT (tune (bool))); connect ( this - , SIGNAL (sendMessage (unsigned, double, unsigned, bool, double)) + , SIGNAL (sendMessage (unsigned, double, unsigned, AudioDevice::Channel, bool, double)) , &m_modulator - , SLOT (send (unsigned, double, unsigned, bool, double)) + , SLOT (open (unsigned, double, unsigned, AudioDevice::Channel, bool, double)) ); // start the sound output thread m_soundOutputThread.start (QThread::HighPriority); + + // setup the waterfall + connect(m_wideGraph.data (), SIGNAL(freezeDecode2(int)),this, + SLOT(freezeDecode(int))); + connect(m_wideGraph.data (), SIGNAL(f11f12(int)),this, + SLOT(bumpFqso(int))); + connect(m_wideGraph.data (), SIGNAL(setXIT2(int)),this, + SLOT(setXIT(int))); + // connect(m_wideGraph.data (), SIGNAL(dialFreqChanged(double)),this, + // SLOT(dialFreqChanged2(double))); + connect (this, &MainWindow::finished, m_wideGraph.data (), &WideGraph::close); + + + // setup the log QSO dialog + connect (m_logDlg.data (), SIGNAL (acceptQSO (bool)), this, SLOT (acceptQSO2 (bool))); + + on_EraseButton_clicked(); QActionGroup* modeGroup = new QActionGroup(this); @@ -117,7 +138,7 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, \ SLOT(doubleClickOnCall2(bool,bool))); setWindowTitle(Program_Title_Version); - connect(&m_detector, &Detector::bytesWritten, this, &MainWindow::dataSink); + connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink); connect(&m_soundInput, SIGNAL(error(QString)), this, SLOT(showSoundInError(QString))); // connect(&m_soundInput, SIGNAL(status(QString)), this, @@ -165,6 +186,7 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, \ ptt0Timer = new QTimer(this); ptt0Timer->setSingleShot(true); + connect (ptt0Timer, SIGNAL (timeout ()), &m_modulator, SLOT (close ())); connect(ptt0Timer, SIGNAL(timeout()), this, SLOT(stopTx2())); ptt1Timer = new QTimer(this); ptt1Timer->setSingleShot(true); @@ -176,6 +198,7 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, \ tuneButtonTimer= new QTimer(this); tuneButtonTimer->setSingleShot(true); + connect (tuneButtonTimer, SIGNAL (timeout ()), &m_modulator, SLOT (close ())); connect(tuneButtonTimer, SIGNAL(timeout()), this, SLOT(on_stopTxButton_clicked())); @@ -318,15 +341,14 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, \ ui->txrb6->setChecked(true); if(m_mode!="JT9" and m_mode!="JT65" and m_mode!="JT9+JT65") m_mode="JT9"; on_actionWide_Waterfall_triggered(); //### - g_pWideGraph->setRxFreq(m_rxFreq); - g_pWideGraph->setTxFreq(m_txFreq); - g_pWideGraph->setLockTxFreq(m_lockTxFreq); - g_pWideGraph->setFmin(m_fMin); - g_pWideGraph->setModeTx(m_mode); - g_pWideGraph->setModeTx(m_modeTx); + m_wideGraph->setRxFreq(m_rxFreq); + m_wideGraph->setTxFreq(m_txFreq); + m_wideGraph->setLockTxFreq(m_lockTxFreq); + m_wideGraph->setModeTx(m_mode); + m_wideGraph->setModeTx(m_modeTx); dialFreqChanged2(m_dialFreq); - connect(g_pWideGraph, SIGNAL(setFreq3(int,int)),this, + connect(m_wideGraph.data (), SIGNAL(setFreq3(int,int)),this, SLOT(setFreq4(int,int))); if(m_mode=="JT9") on_actionJT9_1_triggered(); @@ -341,7 +363,9 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, \ watcher2 = new QFutureWatcher; connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished())); - m_soundInput.start(m_audioInputDevice, RX_SAMPLE_RATE / 10, &m_detector); + m_detector.open (m_audioInputChannel); + m_soundInput.start(m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, RX_SAMPLE_RATE / 10, &m_detector); + Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0)); Q_EMIT muteAudioOutput (false); m_monitoring=!m_monitorStartOFF; // Start with Monitoring ON/OFF @@ -400,125 +424,113 @@ MainWindow::~MainWindow() //-------------------------------------------------------- writeSettings() void MainWindow::writeSettings() { - QString inifile = m_appDir + "/wsjtx.ini"; - QSettings settings(inifile, QSettings::IniFormat); + m_settings->beginGroup("MainWindow"); + m_settings->setValue ("geometry", saveGeometry ()); + m_settings->setValue ("state", saveState ()); + m_settings->setValue("MRUdir", m_path); + m_settings->setValue("TxFirst",m_txFirst); + m_settings->setValue("DXcall",ui->dxCallEntry->text()); + m_settings->setValue("DXgrid",ui->dxGridEntry->text()); + m_settings->endGroup(); - settings.beginGroup("MainWindow"); - settings.setValue("geometry", saveGeometry()); - settings.setValue("MRUdir", m_path); - settings.setValue("TxFirst",m_txFirst); - settings.setValue("DXcall",ui->dxCallEntry->text()); - settings.setValue("DXgrid",ui->dxGridEntry->text()); - if(g_pWideGraph->isVisible()) { - m_wideGraphGeom = g_pWideGraph->geometry(); - settings.setValue("WideGraphGeom",m_wideGraphGeom); - m_fMin=g_pWideGraph->getFmin(); - } - settings.endGroup(); + m_settings->beginGroup("Common"); + m_settings->setValue("MyCall",m_myCall); + m_settings->setValue("MyGrid",m_myGrid); + m_settings->setValue("IDint",m_idInt); + m_settings->setValue("PTTmethod",m_pttMethodIndex); + m_settings->setValue("PTTport",m_pttPort); + m_settings->setValue("SaveDir",m_saveDir); + m_settings->setValue("SoundInName", m_audioInputDevice.deviceName ()); + m_settings->setValue("SoundOutName", m_audioOutputDevice.deviceName ()); - settings.beginGroup("Common"); - settings.setValue("MyCall",m_myCall); - settings.setValue("MyGrid",m_myGrid); - settings.setValue("IDint",m_idInt); - settings.setValue("PTTmethod",m_pttMethodIndex); - settings.setValue("PTTport",m_pttPort); - settings.setValue("SaveDir",m_saveDir); - settings.setValue("SoundInName", m_audioInputDevice.deviceName ()); - settings.setValue("SoundOutName", m_audioOutputDevice.deviceName ()); - settings.setValue("Mode",m_mode); - settings.setValue("ModeTx",m_modeTx); - settings.setValue("SaveNone",ui->actionNone->isChecked()); - settings.setValue("SaveDecoded",ui->actionSave_decoded->isChecked()); - settings.setValue("SaveAll",ui->actionSave_all->isChecked()); - settings.setValue("NDepth",m_ndepth); - settings.setValue("MonitorOFF",m_monitorStartOFF); - settings.setValue("DialFreq",m_dialFreq); - settings.setValue("RxFreq",m_rxFreq); - settings.setValue("TxFreq",m_txFreq); - settings.setValue("InGain",m_inGain); - settings.setValue("PSKReporter",m_pskReporter); - settings.setValue("After73",m_After73); - settings.setValue("Macros",m_macro); + m_settings->setValue ("AudioInputChannel", AudioDevice::toString (m_audioInputChannel)); + m_settings->setValue ("AudioOutputChannel", AudioDevice::toString (m_audioOutputChannel)); + m_settings->setValue("Mode",m_mode); + m_settings->setValue("ModeTx",m_modeTx); + m_settings->setValue("SaveNone",ui->actionNone->isChecked()); + m_settings->setValue("SaveDecoded",ui->actionSave_decoded->isChecked()); + m_settings->setValue("SaveAll",ui->actionSave_all->isChecked()); + m_settings->setValue("NDepth",m_ndepth); + m_settings->setValue("MonitorOFF",m_monitorStartOFF); + m_settings->setValue("DialFreq",m_dialFreq); + m_settings->setValue("RxFreq",m_rxFreq); + m_settings->setValue("TxFreq",m_txFreq); + m_settings->setValue("InGain",m_inGain); + m_settings->setValue("OutAttenuation", ui->outAttenuation->value ()); + m_settings->setValue("PSKReporter",m_pskReporter); + m_settings->setValue("After73",m_After73); + m_settings->setValue("Macros",m_macro); //Band Settings - settings.setValue("BandFrequencies",m_dFreq); - settings.setValue("BandDescriptions",m_bandDescription); - settings.setValue("AntennaDescriptions",m_antDescription); - settings.setValue("toRTTY",m_toRTTY); - settings.setValue("NoSuffix",m_noSuffix); - settings.setValue("dBtoComments",m_dBtoComments); - settings.setValue("catEnabled",m_catEnabled); - settings.setValue("Rig",m_rig); - settings.setValue("RigIndex",m_rigIndex); - settings.setValue("CATport",m_catPort); - settings.setValue("CATportIndex",m_catPortIndex); - settings.setValue("SerialRate",m_serialRate); - settings.setValue("SerialRateIndex",m_serialRateIndex); - settings.setValue("DataBits",m_dataBits); - settings.setValue("DataBitsIndex",m_dataBitsIndex); - settings.setValue("StopBits",m_stopBits); - settings.setValue("StopBitsIndex",m_stopBitsIndex); - settings.setValue("Handshake",m_handshake); - settings.setValue("HandshakeIndex",m_handshakeIndex); - settings.setValue("BandIndex",m_band); - settings.setValue("PromptToLog",m_promptToLog); - settings.setValue("InsertBlank",m_insertBlank); - settings.setValue("DXCCEntity",m_displayDXCCEntity); - settings.setValue("ClearCallGrid",m_clearCallGrid); - settings.setValue("Miles",m_bMiles); - settings.setValue("GUItab",ui->tabWidget->currentIndex()); - settings.setValue("QuickCall",m_quickCall); - settings.setValue("73TxDisable",m_73TxDisable); - settings.setValue("Runaway",m_runaway); - settings.setValue("Tx2QSO",m_tx2QSO); - settings.setValue("MultipleOK",m_bMultipleOK); - settings.setValue("DTR",m_bDTR); - settings.setValue("RTS",m_bRTS); settings.setValue("pttData",m_pttData); - settings.setValue("LogQSOgeom",m_logQSOgeom); - settings.setValue("Polling",m_poll); - settings.setValue("OutBufSize",outBufSize); - settings.setValue("LockTxFreq",m_lockTxFreq); - settings.setValue("SaveTxPower",m_saveTxPower); - settings.setValue("SaveComments",m_saveComments); - settings.setValue("TxPower",m_txPower); - settings.setValue("LogComments",m_logComments); - settings.setValue("Fmin",m_fMin); - settings.setValue("TxSplit",m_bSplit); - settings.setValue("UseXIT",m_bXIT); - settings.setValue("XIT",m_XIT); - settings.setValue("Plus2kHz",m_plus2kHz); - settings.endGroup(); + m_settings->setValue("BandFrequencies",m_dFreq); + m_settings->setValue("BandDescriptions",m_bandDescription); + m_settings->setValue("AntennaDescriptions",m_antDescription); + m_settings->setValue("toRTTY",m_toRTTY); + m_settings->setValue("NoSuffix",m_noSuffix); + m_settings->setValue("dBtoComments",m_dBtoComments); + m_settings->setValue("catEnabled",m_catEnabled); + m_settings->setValue("Rig",m_rig); + m_settings->setValue("RigIndex",m_rigIndex); + m_settings->setValue("CATport",m_catPort); + m_settings->setValue("CATportIndex",m_catPortIndex); + m_settings->setValue("SerialRate",m_serialRate); + m_settings->setValue("SerialRateIndex",m_serialRateIndex); + m_settings->setValue("DataBits",m_dataBits); + m_settings->setValue("DataBitsIndex",m_dataBitsIndex); + m_settings->setValue("StopBits",m_stopBits); + m_settings->setValue("StopBitsIndex",m_stopBitsIndex); + m_settings->setValue("Handshake",m_handshake); + m_settings->setValue("HandshakeIndex",m_handshakeIndex); + m_settings->setValue("BandIndex",m_band); + m_settings->setValue("PromptToLog",m_promptToLog); + m_settings->setValue("InsertBlank",m_insertBlank); + m_settings->setValue("DXCCEntity",m_displayDXCCEntity); + m_settings->setValue("ClearCallGrid",m_clearCallGrid); + m_settings->setValue("Miles",m_bMiles); + m_settings->setValue("GUItab",ui->tabWidget->currentIndex()); + m_settings->setValue("QuickCall",m_quickCall); + m_settings->setValue("73TxDisable",m_73TxDisable); + m_settings->setValue("Runaway",m_runaway); + m_settings->setValue("Tx2QSO",m_tx2QSO); + m_settings->setValue("MultipleOK",m_bMultipleOK); + m_settings->setValue("DTR",m_bDTR); + m_settings->setValue("RTS",m_bRTS); m_settings->setValue("pttData",m_pttData); + m_settings->setValue("Polling",m_poll); + m_settings->setValue("OutBufSize",outBufSize); + m_settings->setValue("LockTxFreq",m_lockTxFreq); + m_settings->setValue("TxSplit",m_bSplit); + m_settings->setValue("UseXIT",m_bXIT); + m_settings->setValue("XIT",m_XIT); + m_settings->setValue("Plus2kHz",m_plus2kHz); + m_settings->endGroup(); } //---------------------------------------------------------- readSettings() void MainWindow::readSettings() { - QString inifile = m_appDir + "/wsjtx.ini"; - QSettings settings(inifile, QSettings::IniFormat); - settings.beginGroup("MainWindow"); - restoreGeometry(settings.value("geometry").toByteArray()); - ui->dxCallEntry->setText(settings.value("DXcall","").toString()); - ui->dxGridEntry->setText(settings.value("DXgrid","").toString()); - m_wideGraphGeom = settings.value("WideGraphGeom", \ - QRect(45,30,726,301)).toRect(); - m_path = settings.value("MRUdir", m_appDir + "/save").toString(); - m_txFirst = settings.value("TxFirst",false).toBool(); + m_settings->beginGroup("MainWindow"); + restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ()); + restoreState (m_settings->value ("state", saveState ()).toByteArray ()); + ui->dxCallEntry->setText(m_settings->value("DXcall","").toString()); + ui->dxGridEntry->setText(m_settings->value("DXgrid","").toString()); + m_path = m_settings->value("MRUdir", m_appDir + "/save").toString(); + m_txFirst = m_settings->value("TxFirst",false).toBool(); ui->txFirstCheckBox->setChecked(m_txFirst); - settings.endGroup(); + m_settings->endGroup(); - settings.beginGroup("Common"); - m_myCall=settings.value("MyCall","").toString(); + m_settings->beginGroup("Common"); + m_myCall=m_settings->value("MyCall","").toString(); morse_(m_myCall.toLatin1().data(),icw,&m_ncw,m_myCall.length()); - m_myGrid=settings.value("MyGrid","").toString(); - m_idInt=settings.value("IDint",0).toInt(); - m_pttMethodIndex=settings.value("PTTmethod",1).toInt(); - m_pttPort=settings.value("PTTport",0).toInt(); - m_saveDir=settings.value("SaveDir",m_appDir + "/save").toString(); + m_myGrid=m_settings->value("MyGrid","").toString(); + m_idInt=m_settings->value("IDint",0).toInt(); + m_pttMethodIndex=m_settings->value("PTTmethod",1).toInt(); + m_pttPort=m_settings->value("PTTport",0).toInt(); + m_saveDir=m_settings->value("SaveDir",m_appDir + "/save").toString(); { // // retrieve audio input device // - QString savedName = settings.value( "SoundInName").toString(); + QString savedName = m_settings->value( "SoundInName").toString(); QList audioInputDevices (QAudioDeviceInfo::availableDevices (QAudio::AudioInput)); // available audio input devices for (QList::const_iterator p = audioInputDevices.begin (); p != audioInputDevices.end (); ++p) { @@ -533,7 +545,7 @@ void MainWindow::readSettings() // // retrieve audio output device // - QString savedName = settings.value("SoundOutName").toString(); + QString savedName = m_settings->value("SoundOutName").toString(); QList audioOutputDevices (QAudioDeviceInfo::availableDevices (QAudio::AudioOutput)); // available audio output devices for (QList::const_iterator p = audioOutputDevices.begin (); p != audioOutputDevices.end (); ++p) { @@ -543,95 +555,98 @@ void MainWindow::readSettings() } } - m_mode=settings.value("Mode","JT9").toString(); - m_modeTx=settings.value("ModeTx","JT9").toString(); + // retrieve audio channel info + m_audioInputChannel = AudioDevice::fromString (m_settings->value ("AudioInputChannel", "Mono").toString ()); + m_audioOutputChannel = AudioDevice::fromString (m_settings->value ("AudioOutputChannel", "Mono").toString ()); + + m_mode=m_settings->value("Mode","JT9").toString(); + m_modeTx=m_settings->value("ModeTx","JT9").toString(); if(m_modeTx=="JT9") ui->pbTxMode->setText("Tx JT9 @"); if(m_modeTx=="JT65") ui->pbTxMode->setText("Tx JT65 #"); - ui->actionNone->setChecked(settings.value("SaveNone",true).toBool()); - ui->actionSave_decoded->setChecked(settings.value( + ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool()); + ui->actionSave_decoded->setChecked(m_settings->value( "SaveDecoded",false).toBool()); - ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool()); - m_dialFreq=settings.value("DialFreq",14.078).toDouble(); - m_rxFreq=settings.value("RxFreq",1500).toInt(); + ui->actionSave_all->setChecked(m_settings->value("SaveAll",false).toBool()); + m_dialFreq=m_settings->value("DialFreq",14.078).toDouble(); + m_rxFreq=m_settings->value("RxFreq",1500).toInt(); ui->RxFreqSpinBox->setValue(m_rxFreq); - m_txFreq=settings.value("TxFreq",1500).toInt(); + m_txFreq=m_settings->value("TxFreq",1500).toInt(); ui->TxFreqSpinBox->setValue(m_txFreq); Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0)); m_saveDecoded=ui->actionSave_decoded->isChecked(); m_saveAll=ui->actionSave_all->isChecked(); - m_ndepth=settings.value("NDepth",3).toInt(); - m_inGain=settings.value("InGain",0).toInt(); + m_ndepth=m_settings->value("NDepth",3).toInt(); + m_inGain=m_settings->value("InGain",0).toInt(); ui->inGain->setValue(m_inGain); - m_monitorStartOFF=settings.value("MonitorOFF",false).toBool(); + + // setup initial value of tx attenuator + ui->outAttenuation->setValue (m_settings->value ("OutAttenuation", 0).toInt ()); + on_outAttenuation_valueChanged (ui->outAttenuation->value ()); + + m_monitorStartOFF=m_settings->value("MonitorOFF",false).toBool(); ui->actionMonitor_OFF_at_startup->setChecked(m_monitorStartOFF); - m_pskReporter=settings.value("PSKReporter",false).toBool(); - m_After73=settings.value("After73",false).toBool(); - m_macro=settings.value("Macros","TNX 73 GL").toStringList(); + m_pskReporter=m_settings->value("PSKReporter",false).toBool(); + m_After73=m_settings->value("After73",false).toBool(); + m_macro=m_settings->value("Macros","TNX 73 GL").toStringList(); //Band Settings - m_dFreq=settings.value("BandFrequencies","").toStringList(); - m_bandDescription=settings.value("BandDescriptions","").toStringList(); - m_antDescription=settings.value("AntennaDescriptions","").toStringList(); - m_toRTTY=settings.value("toRTTY",false).toBool(); + m_dFreq=m_settings->value("BandFrequencies","").toStringList(); + m_bandDescription=m_settings->value("BandDescriptions","").toStringList(); + m_antDescription=m_settings->value("AntennaDescriptions","").toStringList(); + m_toRTTY=m_settings->value("toRTTY",false).toBool(); ui->actionConvert_JT9_x_to_RTTY->setChecked(m_toRTTY); - m_noSuffix=settings.value("NoSuffix",false).toBool(); - m_dBtoComments=settings.value("dBtoComments",false).toBool(); + m_noSuffix=m_settings->value("NoSuffix",false).toBool(); + m_dBtoComments=m_settings->value("dBtoComments",false).toBool(); ui->actionLog_dB_reports_to_Comments->setChecked(m_dBtoComments); - m_rig=settings.value("Rig",214).toInt(); - m_rigIndex=settings.value("RigIndex",100).toInt(); - m_catPort=settings.value("CATport","None").toString(); - m_catPortIndex=settings.value("CATportIndex",0).toInt(); - m_serialRate=settings.value("SerialRate",4800).toInt(); - m_serialRateIndex=settings.value("SerialRateIndex",1).toInt(); - m_dataBits=settings.value("DataBits",8).toInt(); - m_dataBitsIndex=settings.value("DataBitsIndex",1).toInt(); - m_stopBits=settings.value("StopBits",2).toInt(); - m_stopBitsIndex=settings.value("StopBitsIndex",1).toInt(); - m_handshake=settings.value("Handshake","None").toString(); - m_handshakeIndex=settings.value("HandshakeIndex",0).toInt(); - m_band=settings.value("BandIndex",7).toInt(); + m_rig=m_settings->value("Rig",214).toInt(); + m_rigIndex=m_settings->value("RigIndex",100).toInt(); + m_catPort=m_settings->value("CATport","None").toString(); + m_catPortIndex=m_settings->value("CATportIndex",0).toInt(); + m_serialRate=m_settings->value("SerialRate",4800).toInt(); + m_serialRateIndex=m_settings->value("SerialRateIndex",1).toInt(); + m_dataBits=m_settings->value("DataBits",8).toInt(); + m_dataBitsIndex=m_settings->value("DataBitsIndex",1).toInt(); + m_stopBits=m_settings->value("StopBits",2).toInt(); + m_stopBitsIndex=m_settings->value("StopBitsIndex",1).toInt(); + m_handshake=m_settings->value("Handshake","None").toString(); + m_handshakeIndex=m_settings->value("HandshakeIndex",0).toInt(); + m_band=m_settings->value("BandIndex",7).toInt(); ui->bandComboBox->setCurrentIndex(m_band); dialFreqChanged2(m_dialFreq); - m_catEnabled=settings.value("catEnabled",false).toBool(); - m_promptToLog=settings.value("PromptToLog",false).toBool(); + m_catEnabled=m_settings->value("catEnabled",false).toBool(); + m_promptToLog=m_settings->value("PromptToLog",false).toBool(); ui->actionPrompt_to_log_QSO->setChecked(m_promptToLog); - m_insertBlank=settings.value("InsertBlank",false).toBool(); + m_insertBlank=m_settings->value("InsertBlank",false).toBool(); ui->actionBlank_line_between_decoding_periods->setChecked(m_insertBlank); - m_displayDXCCEntity=settings.value("DXCCEntity",false).toBool(); + m_displayDXCCEntity=m_settings->value("DXCCEntity",false).toBool(); ui->actionEnable_DXCC_entity->setChecked(m_displayDXCCEntity); - m_clearCallGrid=settings.value("ClearCallGrid",false).toBool(); + m_clearCallGrid=m_settings->value("ClearCallGrid",false).toBool(); ui->actionClear_DX_Call_and_Grid_after_logging->setChecked(m_clearCallGrid); - m_bMiles=settings.value("Miles",false).toBool(); + m_bMiles=m_settings->value("Miles",false).toBool(); ui->actionDisplay_distance_in_miles->setChecked(m_bMiles); - int n=settings.value("GUItab",0).toInt(); + int n=m_settings->value("GUItab",0).toInt(); ui->tabWidget->setCurrentIndex(n); - m_quickCall=settings.value("QuickCall",false).toBool(); + m_quickCall=m_settings->value("QuickCall",false).toBool(); ui->actionDouble_click_on_call_sets_Tx_Enable->setChecked(m_quickCall); - m_73TxDisable=settings.value("73TxDisable",false).toBool(); + m_73TxDisable=m_settings->value("73TxDisable",false).toBool(); ui->action_73TxDisable->setChecked(m_73TxDisable); - m_runaway=settings.value("Runaway",false).toBool(); + m_runaway=m_settings->value("Runaway",false).toBool(); ui->actionRunaway_Tx_watchdog->setChecked(m_runaway); - m_tx2QSO=settings.value("Tx2QSO",false).toBool(); + m_tx2QSO=m_settings->value("Tx2QSO",false).toBool(); ui->actionTx2QSO->setChecked(m_tx2QSO); - m_bMultipleOK=settings.value("MultipleOK",false).toBool(); + m_bMultipleOK=m_settings->value("MultipleOK",false).toBool(); ui->actionAllow_multiple_instances->setChecked(m_bMultipleOK); - m_bDTR=settings.value("DTR",false).toBool(); - m_bRTS=settings.value("RTS",false).toBool(); m_pttData=settings.value("pttData",false).toBool(); - m_poll=settings.value("Polling",0).toInt(); - m_logQSOgeom=settings.value("LogQSOgeom",QRect(500,400,424,283)).toRect(); - outBufSize=settings.value("OutBufSize",4096).toInt(); - m_lockTxFreq=settings.value("LockTxFreq",false).toBool(); + m_bDTR=m_settings->value("DTR",false).toBool(); + m_bRTS=m_settings->value("RTS",false).toBool(); m_pttData=m_settings->value("pttData",false).toBool(); + m_poll=m_settings->value("Polling",0).toInt(); + outBufSize=m_settings->value("OutBufSize",4096).toInt(); + m_lockTxFreq=m_settings->value("LockTxFreq",false).toBool(); ui->cbTxLock->setChecked(m_lockTxFreq); - m_saveTxPower=settings.value("SaveTxPower",false).toBool(); - m_saveComments=settings.value("SaveComments",false).toBool(); - m_txPower=settings.value("TxPower","").toString(); - m_logComments=settings.value("LogComments","").toString(); - m_fMin=settings.value("fMin",2500).toInt(); - m_bSplit=settings.value("TxSplit",false).toBool(); - m_bXIT=settings.value("UseXIT",false).toBool(); - m_XIT=settings.value("XIT",0).toInt(); - m_plus2kHz=settings.value("Plus2kHz",false).toBool(); + m_bSplit=m_settings->value("TxSplit",false).toBool(); + m_bXIT=m_settings->value("UseXIT",false).toBool(); + m_XIT=m_settings->value("XIT",0).toInt(); + m_plus2kHz=m_settings->value("Plus2kHz",false).toBool(); ui->cbPlus2kHz->setChecked(m_plus2kHz); - settings.endGroup(); + m_settings->endGroup(); if(m_ndepth==1) ui->actionQuickDecode->setChecked(true); if(m_ndepth==2) ui->actionMediumDecode->setChecked(true); @@ -641,7 +656,7 @@ void MainWindow::readSettings() } //-------------------------------------------------------------- dataSink() -void MainWindow::dataSink(qint64 bytes) +void MainWindow::dataSink(qint64 frames) { static float s[NSMAX]; static int ihsym=0; @@ -661,8 +676,8 @@ void MainWindow::dataSink(qint64 bytes) // Get power, spectrum, and ihsym trmin=m_TRperiod/60; slope=0.0; - if(g_pWideGraph!=NULL) slope=(float)g_pWideGraph->getSlope(); - int k (bytes / sizeof (jt9com_.d2[0]) - 1); + slope=(float)m_wideGraph->getSlope(); + int k (frames - 1); symspec_(&k,&trmin,&m_nsps,&m_inGain,&slope,&px,s,&df3,&ihsym,&npts8); if(ihsym <=0) return; QString t; @@ -670,7 +685,7 @@ void MainWindow::dataSink(qint64 bytes) t.sprintf(" Rx noise: %5.1f ",px); signalMeter->setValue(px); // Update thermometer if(m_monitoring || m_diskData) { - g_pWideGraph->dataSink2(s,df3,ihsym,m_diskData); + m_wideGraph->dataSink2(s,df3,ihsym,m_diskData); } if(ihsym == m_hsymStop) { @@ -716,6 +731,8 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog dlg.m_saveDir=m_saveDir; dlg.m_audioInputDevice = m_audioInputDevice; dlg.m_audioOutputDevice = m_audioOutputDevice; + dlg.m_audioInputChannel = m_audioInputChannel; + dlg.m_audioOutputChannel = m_audioOutputChannel; dlg.m_pskReporter=m_pskReporter; dlg.m_After73=m_After73; dlg.m_macro=m_macro; @@ -761,6 +778,8 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog m_saveDir=dlg.m_saveDir; m_audioInputDevice = dlg.m_audioInputDevice; m_audioOutputDevice = dlg.m_audioOutputDevice; + m_audioInputChannel = dlg.m_audioInputChannel; + m_audioOutputChannel = dlg.m_audioOutputChannel; m_macro=dlg.m_macro; m_dFreq=dlg.m_dFreq; m_antDescription=dlg.m_antDescription; @@ -796,7 +815,10 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog m_After73=dlg.m_After73; if(dlg.m_restartSoundIn) { - m_soundInput.start(m_audioInputDevice, RX_SAMPLE_RATE / 10, &m_detector); + m_soundInput.stop (); + m_detector.close (); + m_detector.open (m_audioInputChannel); + m_soundInput.start(m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, RX_SAMPLE_RATE / 10, &m_detector); } if(dlg.m_restartSoundOut) { @@ -832,7 +854,7 @@ void MainWindow::on_monitorButton_clicked() //Monitor { m_monitoring=true; m_detector.setMonitoring(true); - m_soundInput.start(m_audioInputDevice, RX_SAMPLE_RATE / 10, &m_detector); + // m_soundInput.start(m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, RX_SAMPLE_RATE / 10, &m_detector); m_diskData=false; } @@ -963,13 +985,13 @@ void MainWindow::bumpFqso(int n) //bumpFqso() int i; bool ctrl = (n>=100); n=n%100; - i=g_pWideGraph->rxFreq(); + i=m_wideGraph->rxFreq(); if(n==11) i--; if(n==12) i++; - g_pWideGraph->setRxFreq(i); + m_wideGraph->setRxFreq(i); if(ctrl) { ui->TxFreqSpinBox->setValue(i); - g_pWideGraph->setTxFreq(i); + m_wideGraph->setTxFreq(i); } } @@ -992,7 +1014,7 @@ void MainWindow::dialFreqChanged2(double f) } ui->labDialFreq->setText(t); statusChanged(); - if(g_pWideGraph!=NULL) g_pWideGraph->setDialFreq(m_dialFreq); + m_wideGraph->setDialFreq(m_dialFreq); } void MainWindow::statusChanged() @@ -1047,16 +1069,16 @@ void MainWindow::on_actionExit_triggered() //Exit() OnExit(); } -void MainWindow::closeEvent(QCloseEvent*) +void MainWindow::closeEvent(QCloseEvent * e) { + writeSettings (); OnExit(); + QMainWindow::closeEvent (e); } void MainWindow::OnExit() { m_guiTimer.stop (); - g_pWideGraph->saveSettings(); - writeSettings(); if(m_fname != "") killFile(); m_killAll=true; mem_jt9->detach(); @@ -1076,7 +1098,6 @@ void MainWindow::on_stopButton_clicked() //stopButton { m_monitoring=false; m_detector.setMonitoring(m_monitoring); - m_soundInput.stop (); m_loopall=false; } @@ -1095,24 +1116,7 @@ void MainWindow::on_actionOnline_Users_Guide_triggered() //Display manual void MainWindow::on_actionWide_Waterfall_triggered() //Display Waterfalls { - if(g_pWideGraph==NULL) { - g_pWideGraph = new WideGraph(0); - g_pWideGraph->setWindowTitle("Wide Graph"); - g_pWideGraph->setGeometry(m_wideGraphGeom); - Qt::WindowFlags flags = Qt::WindowCloseButtonHint | - Qt::WindowMinimizeButtonHint; - g_pWideGraph->setWindowFlags(flags); - connect(g_pWideGraph, SIGNAL(freezeDecode2(int)),this, - SLOT(freezeDecode(int))); - connect(g_pWideGraph, SIGNAL(f11f12(int)),this, - SLOT(bumpFqso(int))); - connect(g_pWideGraph, SIGNAL(setXIT2(int)),this, - SLOT(setXIT(int))); -// connect(g_pWideGraph, SIGNAL(dialFreqChanged(double)),this, -// SLOT(dialFreqChanged2(double))); - connect (this, &MainWindow::finished, g_pWideGraph, &WideGraph::close); - } - g_pWideGraph->show(); + m_wideGraph->show(); } void MainWindow::on_actionOpen_triggered() //Open File @@ -1295,10 +1299,10 @@ void MainWindow::on_DecodeButton_clicked() //Decode request void MainWindow::freezeDecode(int n) //freezeDecode() { bool ctrl = (n>=100); - int i=g_pWideGraph->rxFreq(); + int i=m_wideGraph->rxFreq(); if(ctrl) { ui->TxFreqSpinBox->setValue(i); - g_pWideGraph->setTxFreq(i); + m_wideGraph->setTxFreq(i); } if((n%100)==2) on_DecodeButton_clicked(); } @@ -1316,13 +1320,13 @@ void MainWindow::decode() //decode() jt9com_.nutc=100*ihr + imin; } - jt9com_.nfqso=g_pWideGraph->rxFreq(); + jt9com_.nfqso=m_wideGraph->rxFreq(); jt9com_.ndepth=m_ndepth; jt9com_.ndiskdat=0; if(m_diskData) jt9com_.ndiskdat=1; - jt9com_.nfa=g_pWideGraph->nStartFreq(); - jt9com_.nfSplit=g_pWideGraph->getFmin(); - jt9com_.nfb=g_pWideGraph->getFmax(); + jt9com_.nfa=m_wideGraph->nStartFreq(); + jt9com_.nfSplit=m_wideGraph->getFmin(); + jt9com_.nfb=m_wideGraph->getFmax(); jt9com_.ntol=20; if(jt9com_.nutc < m_nutc0) m_RxLog |= 1; //Date and Time to all.txt m_nutc0=jt9com_.nutc; @@ -1420,7 +1424,7 @@ void MainWindow::readFromStdout() //readFromStdout QString bg="white"; if(t.indexOf(" CQ ")>0) bg="#66ff66"; //green if(m_myCall!="" and t.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red - bool bQSO=abs(t.mid(14,4).toInt() - g_pWideGraph->rxFreq()) <= 10; + bool bQSO=abs(t.mid(14,4).toInt() - m_wideGraph->rxFreq()) <= 10; QString t1=t.replace("\n","").mid(0,t.length()-4); // if enabled add the DXCC entity and B4 status to the end of the preformated text line t1 @@ -1752,7 +1756,6 @@ void MainWindow::guiUpdate() signalMeter->setValue(0); m_monitoring=false; m_detector.setMonitoring(false); - m_soundInput.stop (); m_btxok=true; Q_EMIT muteAudioOutput (false); m_transmitting=true; @@ -1881,7 +1884,6 @@ void MainWindow::startTx2() signalMeter->setValue(0); m_monitoring=false; m_detector.setMonitoring(false); - m_soundInput.stop (); m_btxok=true; Q_EMIT muteAudioOutput (false); m_transmitting=true; @@ -1900,7 +1902,6 @@ void MainWindow::stopTx() lab1->setText(""); ptt0Timer->start(200); //Sequencer delay m_monitoring=true; - m_soundInput.start(m_audioInputDevice, RX_SAMPLE_RATE / 10, &m_detector); m_detector.setMonitoring(true); } @@ -2046,7 +2047,7 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) int nfreq=t4.at(3).toInt(); if(t4.at(1)=="Tx") nfreq=t4.at(2).toInt(); - g_pWideGraph->setRxFreq(nfreq); //Set Rx freq + m_wideGraph->setRxFreq(nfreq); //Set Rx freq if(t4.at(1)=="Tx") { if(ctrl) ui->TxFreqSpinBox->setValue(nfreq); //Set Tx freq return; @@ -2054,12 +2055,12 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) if(t4.at(4)=="@") { m_modeTx="JT9"; ui->pbTxMode->setText("Tx JT9 @"); - g_pWideGraph->setModeTx(m_modeTx); + m_wideGraph->setModeTx(m_modeTx); } if(t4.at(4)=="#") { m_modeTx="JT65"; ui->pbTxMode->setText("Tx JT65 #"); - g_pWideGraph->setModeTx(m_modeTx); + m_wideGraph->setModeTx(m_modeTx); } QString firstcall=t4.at(5); // Don't change Tx freq if a station is calling me, unless m_lockTxFreq @@ -2470,27 +2471,14 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button if(m_hisCall=="") return; m_dateTimeQSO=QDateTime::currentDateTimeUtc(); - logDlg = new LogQSO(0); - logDlg->m_saveTxPower=m_saveTxPower; - logDlg->m_saveComments=m_saveComments; - logDlg->m_txPower=m_txPower; - logDlg->m_comments=m_logComments; - logDlg->initLogQSO(m_hisCall,m_hisGrid,m_modeTx,m_rptSent,m_rptRcvd, + m_logDlg->initLogQSO(m_hisCall,m_hisGrid,m_modeTx,m_rptSent,m_rptRcvd, m_dateTimeQSO,m_dialFreq+m_txFreq/1.0e6, m_myCall,m_myGrid,m_noSuffix,m_toRTTY,m_dBtoComments); - connect(logDlg, SIGNAL(acceptQSO(bool)),this,SLOT(acceptQSO2(bool))); - if(m_logQSOgeom != QRect(500,400,424,283)) logDlg->setGeometry(m_logQSOgeom); - logDlg->show(); } void MainWindow::acceptQSO2(bool accepted) { if(accepted) { - m_logQSOgeom=logDlg->geometry(); - m_saveTxPower=logDlg->m_saveTxPower; - m_saveComments=logDlg->m_saveComments; - m_txPower=logDlg->m_txPower; - m_logComments=logDlg->m_comments; m_logBook.addAsWorked(m_hisCall); if(m_clearCallGrid) { m_hisCall=""; @@ -2516,9 +2504,9 @@ void MainWindow::on_actionJT9_1_triggered() lab2->setStyleSheet("QLabel{background-color: #ff6ec7}"); lab2->setText(m_mode); ui->actionJT9_1->setChecked(true); - g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - g_pWideGraph->setMode(m_mode); - g_pWideGraph->setModeTx(m_modeTx); + m_wideGraph->setPeriod(m_TRperiod,m_nsps); + m_wideGraph->setMode(m_mode); + m_wideGraph->setModeTx(m_modeTx); ui->pbTxMode->setEnabled(false); } @@ -2533,9 +2521,9 @@ void MainWindow::on_actionJT65_triggered() lab2->setStyleSheet("QLabel{background-color: #ffff00}"); lab2->setText(m_mode); ui->actionJT65->setChecked(true); - g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - g_pWideGraph->setMode(m_mode); - g_pWideGraph->setModeTx(m_modeTx); + m_wideGraph->setPeriod(m_TRperiod,m_nsps); + m_wideGraph->setMode(m_mode); + m_wideGraph->setModeTx(m_modeTx); ui->pbTxMode->setEnabled(false); } @@ -2550,16 +2538,16 @@ void MainWindow::on_actionJT9_JT65_triggered() lab2->setStyleSheet("QLabel{background-color: #ffa500}"); lab2->setText(m_mode); ui->actionJT9_JT65->setChecked(true); - g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - g_pWideGraph->setMode(m_mode); - g_pWideGraph->setModeTx(m_modeTx); + m_wideGraph->setPeriod(m_TRperiod,m_nsps); + m_wideGraph->setMode(m_mode); + m_wideGraph->setModeTx(m_modeTx); ui->pbTxMode->setEnabled(true); } void MainWindow::on_TxFreqSpinBox_valueChanged(int n) { m_txFreq=n; - if(g_pWideGraph!=NULL) g_pWideGraph->setTxFreq(n); + m_wideGraph->setTxFreq(n); if(m_lockTxFreq) ui->RxFreqSpinBox->setValue(n); Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0)); } @@ -2567,7 +2555,7 @@ void MainWindow::on_TxFreqSpinBox_valueChanged(int n) void MainWindow::on_RxFreqSpinBox_valueChanged(int n) { m_rxFreq=n; - if(g_pWideGraph!=NULL) g_pWideGraph->setRxFreq(n); + m_wideGraph->setRxFreq(n); if(m_lockTxFreq) ui->TxFreqSpinBox->setValue(n); } @@ -2719,10 +2707,9 @@ void MainWindow::on_bandComboBox_activated(int index) ret=rig->setFreq(MHz(m_dialFreq)); if(m_bSplit or m_bXIT) setXIT(m_txFreq); - if(g_pWideGraph!=NULL) { - bumpFqso(11); - bumpFqso(12); - } + bumpFqso(11); + bumpFqso(12); + if(ret!=RIG_OK) { rt.sprintf("Set rig frequency failed: %d",ret); msgBox(rt); @@ -2973,13 +2960,13 @@ void MainWindow::on_actionAllow_multiple_instances_triggered(bool checked) void MainWindow::on_pbR2T_clicked() { - int n=g_pWideGraph->rxFreq(); + int n=m_wideGraph->rxFreq(); ui->TxFreqSpinBox->setValue(n); } void MainWindow::on_pbT2R_clicked() { - g_pWideGraph->setRxFreq(m_txFreq); + m_wideGraph->setRxFreq(m_txFreq); } @@ -3009,7 +2996,7 @@ void MainWindow::on_pbTxMode_clicked() m_modeTx="JT9"; ui->pbTxMode->setText("Tx JT9 @"); } - g_pWideGraph->setModeTx(m_modeTx); + m_wideGraph->setModeTx(m_modeTx); statusChanged(); } @@ -3045,7 +3032,7 @@ void MainWindow::setFreq4(int rxFreq, int txFreq) void MainWindow::on_cbTxLock_clicked(bool checked) { m_lockTxFreq=checked; - g_pWideGraph->setLockTxFreq(m_lockTxFreq); + m_wideGraph->setLockTxFreq(m_lockTxFreq); if(m_lockTxFreq) on_pbR2T_clicked(); } @@ -3089,11 +3076,18 @@ void MainWindow::transmit (double snr) { if (m_modeTx == "JT65") { - Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0), true, snr); + Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0), m_audioOutputChannel, true, snr); } else { - Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0), true, snr); + Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0), m_audioOutputChannel, true, snr); } - Q_EMIT startAudioOutputStream (m_audioOutputDevice); + Q_EMIT startAudioOutputStream (m_audioOutputDevice, AudioDevice::Mono == m_audioOutputChannel ? 1 : 2); +} + +void MainWindow::on_outAttenuation_valueChanged (int a) +{ + qreal dBAttn (a / 10.); // slider interpreted as hundredths of a dB + ui->outAttenuation->setToolTip (tr ("Transmit digital gain ") + (a ? QString::number (-dBAttn, 'f', 1) : "0") + "dB"); + Q_EMIT outAttenuationChanged (dBAttn); } diff --git a/mainwindow.h b/mainwindow.h index 8e0e422f8..fc8b5030a 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "soundin.h" #include "soundout.h" @@ -39,13 +40,17 @@ namespace Ui { class MainWindow; } +class QSettings; +class WideGraph; +class LogQSO; + class MainWindow : public QMainWindow { Q_OBJECT // Multiple instances: call MainWindow() with *thekey public: - explicit MainWindow(QSharedMemory *shdmem, QString *thekey, \ + explicit MainWindow(QSettings *, QSharedMemory *shdmem, QString *thekey, \ qint32 fontSize2, qint32 fontWeight2, \ QWidget *parent = 0); ~MainWindow(); @@ -54,7 +59,7 @@ public slots: void showSoundInError(const QString& errorMsg); void showSoundOutError(const QString& errorMsg); void showStatusMessage(const QString& statusMsg); - void dataSink(qint64 bytes); + void dataSink(qint64 frames); void diskDat(); void diskWriteFinished(); void freezeDecode(int n); @@ -175,20 +180,27 @@ private slots: void on_cbTxLock_clicked(bool checked); void on_actionTx2QSO_triggered(bool checked); void on_cbPlus2kHz_toggled(bool checked); + void on_outAttenuation_valueChanged (int); private: - Q_SIGNAL void startAudioOutputStream (QAudioDeviceInfo); + Q_SIGNAL void startAudioOutputStream (QAudioDeviceInfo, unsigned channels); Q_SIGNAL void stopAudioOutputStream (); Q_SIGNAL void finished (); Q_SIGNAL void muteAudioOutput (bool = true); Q_SIGNAL void transmitFrequency (unsigned); Q_SIGNAL void endTransmitMessage (); Q_SIGNAL void tune (bool = true); - Q_SIGNAL void sendMessage (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, bool synchronize = true, double dBSNR = 99.); + Q_SIGNAL void sendMessage (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, AudioDevice::Channel, bool synchronize = true, double dBSNR = 99.); + Q_SIGNAL void outAttenuationChanged (qreal); private: + QSettings * m_settings; Ui::MainWindow *ui; + // other windows + QScopedPointer m_wideGraph; + QScopedPointer m_logDlg; + double m_dialFreq; qint64 m_msErase; @@ -213,10 +225,12 @@ private: Detector m_detector; QAudioDeviceInfo m_audioInputDevice; + AudioDevice::Channel m_audioInputChannel; SoundInput m_soundInput; Modulator m_modulator; QAudioDeviceInfo m_audioOutputDevice; + AudioDevice::Channel m_audioOutputChannel; SoundOutput m_soundOutput; QThread m_soundOutputThread; @@ -242,7 +256,6 @@ private: qint32 m_repeatMsg; qint32 m_watchdogLimit; qint32 m_poll; - qint32 m_fMin; qint32 m_fMax; qint32 m_bad; @@ -292,8 +305,6 @@ private: bool m_pttData; bool m_dontReadFreq; bool m_lockTxFreq; - bool m_saveTxPower; - bool m_saveComments; bool m_tx2QSO; bool m_CATerror; bool m_bSplit; @@ -304,9 +315,6 @@ private: float m_pctZap; - QRect m_wideGraphGeom; - QRect m_logQSOgeom; - QLabel* lab1; // labels in status bar QLabel* lab2; QLabel* lab3; @@ -361,8 +369,6 @@ private: QString m_msgSent0; QString m_fileToSave; QString m_QSOmsg; - QString m_txPower; - QString m_logComments; QStringList m_macro; QStringList m_dFreq; // per band frequency in MHz as a string diff --git a/mainwindow.ui b/mainwindow.ui index 769b730e9..5180a2594 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 760 - 552 + 523 @@ -1148,6 +1148,19 @@ p, li { white-space: pre-wrap; } + + + + false + + + Toggle Tx mode + + + Tx JT9 + + + @@ -1193,6 +1206,16 @@ p, li { white-space: pre-wrap; } + + + + Add 2 kHz to requested dial frequency + + + +2 kHz + + + @@ -2062,16 +2085,19 @@ p, li { white-space: pre-wrap; } - - - - false + + + + + 15 + 15 + - Toggle Tx mode + <html><head/><body><p>If orange, click to read dial frequency</p></body></html> - Tx JT9 + @@ -2091,32 +2117,6 @@ p, li { white-space: pre-wrap; } - - - - Add 2 kHz to requested dial frequency - - - +2 kHz - - - - - - - - 15 - 15 - - - - <html><head/><body><p>If orange, click to read dial frequency</p></body></html> - - - - - - @@ -2225,6 +2225,35 @@ p, li { white-space: pre-wrap; } + + + + Pwr + + + + + + + 0 + + + Qt::Vertical + + + true + + + true + + + QSlider::TicksBelow + + + 0 + + + @@ -2235,7 +2264,7 @@ p, li { white-space: pre-wrap; } 0 0 760 - 20 + 25 diff --git a/meterwidget.cpp b/meterwidget.cpp index 6a464a015..b48aa65d0 100644 --- a/meterwidget.cpp +++ b/meterwidget.cpp @@ -1,51 +1,51 @@ -// Simple bargraph meter -// Implemented by Edson Pereira PY2SDR - -#include "meterwidget.h" - -MeterWidget::MeterWidget(QWidget *parent) : - QWidget(parent), - m_signal(0) -{ - for ( int i = 0; i < 10; i++ ) { - signalQueue.enqueue(0); - } -} - -void MeterWidget::setValue(int value) -{ - m_signal = value; - signalQueue.enqueue(value); - signalQueue.dequeue(); - - // Get signal peak - int tmp = 0; - for (int i = 0; i < signalQueue.size(); ++i) { - if (signalQueue.at(i) > tmp) - tmp = signalQueue.at(i); - } - m_sigPeak = tmp; - - update(); -} - -void MeterWidget::paintEvent( QPaintEvent * ) -{ - int pos; - QPainter p; - - p.begin(this); - - // Sanitize - m_signal = m_signal < 0 ? 0 : m_signal; - m_signal = m_signal > 60 ? 60 : m_signal; - - pos = m_signal * 2; - QRect r(0, height() - pos, width(), pos ); - p.fillRect(r, QColor( 255, 150, 0 )); - - // Draw peak hold indicator - p.setPen(Qt::black); - pos = m_sigPeak * 2; - p.drawLine(0, height() - pos, 10, height() - pos); -} +// Simple bargraph meter +// Implemented by Edson Pereira PY2SDR + +#include "meterwidget.h" + +MeterWidget::MeterWidget(QWidget *parent) : + QWidget(parent), + m_signal(0) +{ + for ( int i = 0; i < 10; i++ ) { + signalQueue.enqueue(0); + } +} + +void MeterWidget::setValue(int value) +{ + m_signal = value; + signalQueue.enqueue(value); + signalQueue.dequeue(); + + // Get signal peak + int tmp = 0; + for (int i = 0; i < signalQueue.size(); ++i) { + if (signalQueue.at(i) > tmp) + tmp = signalQueue.at(i); + } + m_sigPeak = tmp; + + update(); +} + +void MeterWidget::paintEvent( QPaintEvent * ) +{ + int pos; + QPainter p; + + p.begin(this); + + // Sanitize + m_signal = m_signal < 0 ? 0 : m_signal; + m_signal = m_signal > 60 ? 60 : m_signal; + + pos = m_signal * 2; + QRect r(0, height() - pos, width(), pos ); + p.fillRect(r, QColor( 255, 150, 0 )); + + // Draw peak hold indicator + p.setPen(Qt::black); + pos = m_sigPeak * 2; + p.drawLine(0, height() - pos, 10, height() - pos); +} diff --git a/meterwidget.h b/meterwidget.h index af491fd23..7b51efb65 100644 --- a/meterwidget.h +++ b/meterwidget.h @@ -1,30 +1,30 @@ -#ifndef METERWIDGET_H -#define METERWIDGET_H - -#include -#include -#include - -class MeterWidget : public QWidget -{ - Q_OBJECT -public: - explicit MeterWidget(QWidget *parent = 0); - -signals: - -public slots: - void setValue(int value); - -private: - QQueue signalQueue; - - int m_signal; - int m_sigPeak; - -protected: - void paintEvent( QPaintEvent * ); - -}; - -#endif // METERWIDGET_H +#ifndef METERWIDGET_H +#define METERWIDGET_H + +#include +#include +#include + +class MeterWidget : public QWidget +{ + Q_OBJECT +public: + explicit MeterWidget(QWidget *parent = 0); + +signals: + +public slots: + void setValue(int value); + +private: + QQueue signalQueue; + + int m_signal; + int m_sigPeak; + +protected: + void paintEvent( QPaintEvent * ); + +}; + +#endif // METERWIDGET_H diff --git a/psk_reporter.cpp b/psk_reporter.cpp index cedf9b5a7..c991de57b 100644 --- a/psk_reporter.cpp +++ b/psk_reporter.cpp @@ -1,112 +1,112 @@ -// KISS Interface for posting spots to PSK Reporter web site -// Implemented by Edson Pereira PY2SDR -// -// Reports will be sent in batch mode every 5 minutes. - -#include "psk_reporter.h" - -PSK_Reporter::PSK_Reporter(QObject *parent) : - QObject(parent), - m_sequenceNumber(0) -{ - m_header_h = "000Allllttttttttssssssssiiiiiiii"; - - // We use 50E2 and 50E3 for link Id - m_rxInfoDescriptor_h = "0003002C50E200040000" - "8002FFFF0000768F" // 2. Rx Call - "8004FFFF0000768F" // 4. Rx Grid - "8008FFFF0000768F" // 8. Rx Soft - "8009FFFF0000768F" // 9. Rx Antenna - "0000"; - - m_txInfoDescriptor_h = "0002003C50E30007" - "8001FFFF0000768F" // 1. Tx Call - "800500040000768F" // 5. Tx Freq - "800600010000768F" // 6. Tx snr - "800AFFFF0000768F" // 10. Tx Mode - "8003FFFF0000768F" // 3. Tx Grid - "800B00010000768F" // 11. Tx info src - "00960004"; // Report time - - - qsrand(QDateTime::currentDateTime().toTime_t()); - m_randomId_h = QString("%1").arg(qrand(),8,16,QChar('0')); - - m_udpSocket = new QUdpSocket(this); - - reportTimer = new QTimer(this); - connect(reportTimer, SIGNAL(timeout()), this, SLOT(sendReport())); - reportTimer->start(5*60*1000); // 5 minutes; -} - -void PSK_Reporter::setLocalStation(QString call, QString gridSquare, QString antenna, QString programInfo) -{ - m_rxCall = call; - m_rxGrid = gridSquare; - m_rxAnt = antenna; - m_progId = programInfo; - //qDebug() << "PSK_Reporter::setLocalStation. Antenna:" << antenna; -} - -void PSK_Reporter::addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time ) -{ - QHash spot; - spot["call"] = call; - spot["grid"] = grid; - spot["snr"] = snr; - spot["freq"] = freq; - spot["mode"] = mode; - spot["time"] = time; - m_spotQueue.enqueue(spot); -} - -void PSK_Reporter::sendReport() -{ - QString report_h; - - // Header - QString header_h = m_header_h; - header_h.replace("tttttttt", QString("%1").arg(QDateTime::currentDateTime().toTime_t(),8,16,QChar('0'))); - header_h.replace("ssssssss", QString("%1").arg(++m_sequenceNumber,8,16,QChar('0'))); - header_h.replace("iiiiiiii", m_randomId_h); - - // Receiver information - QString rxInfoData_h = "50E2llll"; - rxInfoData_h += QString("%1").arg(m_rxCall.length(),2,16,QChar('0')) + m_rxCall.toUtf8().toHex(); - rxInfoData_h += QString("%1").arg(m_rxGrid.length(),2,16,QChar('0')) + m_rxGrid.toUtf8().toHex(); - rxInfoData_h += QString("%1").arg(m_progId.length(),2,16,QChar('0')) + m_progId.toUtf8().toHex(); - rxInfoData_h += QString("%1").arg(m_rxAnt.length(),2,16,QChar('0')) + m_rxAnt.toUtf8().toHex(); - rxInfoData_h += "0000"; - rxInfoData_h.replace("50E2llll", "50E2" + QString("%1").arg(rxInfoData_h.length()/2,4,16,QChar('0'))); - - // Sender information - if (! m_spotQueue.isEmpty()) { - QString txInfoData_h = "50E3llll"; - while (!m_spotQueue.isEmpty()) { - QHash spot = m_spotQueue.dequeue(); - txInfoData_h += QString("%1").arg(spot["call"].length(),2,16,QChar('0')) + spot["call"].toUtf8().toHex(); - txInfoData_h += QString("%1").arg(spot["freq"].toLongLong(),8,16,QChar('0')); - txInfoData_h += QString("%1").arg(spot["snr"].toInt(),8,16,QChar('0')).right(2); - txInfoData_h += QString("%1").arg(spot["mode"].length(),2,16,QChar('0')) + spot["mode"].toUtf8().toHex(); - txInfoData_h += QString("%1").arg(spot["grid"].length(),2,16,QChar('0')) + spot["grid"].toUtf8().toHex(); - txInfoData_h += QString("%1").arg(1,2,16,QChar('0')); // REPORTER_SOURCE_AUTOMATIC - txInfoData_h += QString("%1").arg(spot["time"].toInt(),8,16,QChar('0')); - } - txInfoData_h += "0000"; - txInfoData_h.replace("50E3llll", "50E3" + QString("%1").arg(txInfoData_h.length()/2,4,16,QChar('0'))); - report_h = header_h + m_rxInfoDescriptor_h + m_txInfoDescriptor_h + rxInfoData_h + txInfoData_h; - //qDebug() << "Sending Report TX: "; - } else { - report_h = header_h + m_rxInfoDescriptor_h + rxInfoData_h; - //qDebug() << "Sending Report RX: "; - } - - report_h.replace("000Allll", "000A" + QString("%1").arg(report_h.length()/2,4,16,QChar('0'))); - QByteArray report = QByteArray::fromHex(report_h.toUtf8()); - - // Get IP address for pskreporter.info and send report via UDP - QHostInfo info = QHostInfo::fromName("report.pskreporter.info"); - m_udpSocket->writeDatagram(report,info.addresses().at(0),4739); -} - - +// KISS Interface for posting spots to PSK Reporter web site +// Implemented by Edson Pereira PY2SDR +// +// Reports will be sent in batch mode every 5 minutes. + +#include "psk_reporter.h" + +PSK_Reporter::PSK_Reporter(QObject *parent) : + QObject(parent), + m_sequenceNumber(0) +{ + m_header_h = "000Allllttttttttssssssssiiiiiiii"; + + // We use 50E2 and 50E3 for link Id + m_rxInfoDescriptor_h = "0003002C50E200040000" + "8002FFFF0000768F" // 2. Rx Call + "8004FFFF0000768F" // 4. Rx Grid + "8008FFFF0000768F" // 8. Rx Soft + "8009FFFF0000768F" // 9. Rx Antenna + "0000"; + + m_txInfoDescriptor_h = "0002003C50E30007" + "8001FFFF0000768F" // 1. Tx Call + "800500040000768F" // 5. Tx Freq + "800600010000768F" // 6. Tx snr + "800AFFFF0000768F" // 10. Tx Mode + "8003FFFF0000768F" // 3. Tx Grid + "800B00010000768F" // 11. Tx info src + "00960004"; // Report time + + + qsrand(QDateTime::currentDateTime().toTime_t()); + m_randomId_h = QString("%1").arg(qrand(),8,16,QChar('0')); + + m_udpSocket = new QUdpSocket(this); + + reportTimer = new QTimer(this); + connect(reportTimer, SIGNAL(timeout()), this, SLOT(sendReport())); + reportTimer->start(5*60*1000); // 5 minutes; +} + +void PSK_Reporter::setLocalStation(QString call, QString gridSquare, QString antenna, QString programInfo) +{ + m_rxCall = call; + m_rxGrid = gridSquare; + m_rxAnt = antenna; + m_progId = programInfo; + //qDebug() << "PSK_Reporter::setLocalStation. Antenna:" << antenna; +} + +void PSK_Reporter::addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time ) +{ + QHash spot; + spot["call"] = call; + spot["grid"] = grid; + spot["snr"] = snr; + spot["freq"] = freq; + spot["mode"] = mode; + spot["time"] = time; + m_spotQueue.enqueue(spot); +} + +void PSK_Reporter::sendReport() +{ + QString report_h; + + // Header + QString header_h = m_header_h; + header_h.replace("tttttttt", QString("%1").arg(QDateTime::currentDateTime().toTime_t(),8,16,QChar('0'))); + header_h.replace("ssssssss", QString("%1").arg(++m_sequenceNumber,8,16,QChar('0'))); + header_h.replace("iiiiiiii", m_randomId_h); + + // Receiver information + QString rxInfoData_h = "50E2llll"; + rxInfoData_h += QString("%1").arg(m_rxCall.length(),2,16,QChar('0')) + m_rxCall.toUtf8().toHex(); + rxInfoData_h += QString("%1").arg(m_rxGrid.length(),2,16,QChar('0')) + m_rxGrid.toUtf8().toHex(); + rxInfoData_h += QString("%1").arg(m_progId.length(),2,16,QChar('0')) + m_progId.toUtf8().toHex(); + rxInfoData_h += QString("%1").arg(m_rxAnt.length(),2,16,QChar('0')) + m_rxAnt.toUtf8().toHex(); + rxInfoData_h += "0000"; + rxInfoData_h.replace("50E2llll", "50E2" + QString("%1").arg(rxInfoData_h.length()/2,4,16,QChar('0'))); + + // Sender information + if (! m_spotQueue.isEmpty()) { + QString txInfoData_h = "50E3llll"; + while (!m_spotQueue.isEmpty()) { + QHash spot = m_spotQueue.dequeue(); + txInfoData_h += QString("%1").arg(spot["call"].length(),2,16,QChar('0')) + spot["call"].toUtf8().toHex(); + txInfoData_h += QString("%1").arg(spot["freq"].toLongLong(),8,16,QChar('0')); + txInfoData_h += QString("%1").arg(spot["snr"].toInt(),8,16,QChar('0')).right(2); + txInfoData_h += QString("%1").arg(spot["mode"].length(),2,16,QChar('0')) + spot["mode"].toUtf8().toHex(); + txInfoData_h += QString("%1").arg(spot["grid"].length(),2,16,QChar('0')) + spot["grid"].toUtf8().toHex(); + txInfoData_h += QString("%1").arg(1,2,16,QChar('0')); // REPORTER_SOURCE_AUTOMATIC + txInfoData_h += QString("%1").arg(spot["time"].toInt(),8,16,QChar('0')); + } + txInfoData_h += "0000"; + txInfoData_h.replace("50E3llll", "50E3" + QString("%1").arg(txInfoData_h.length()/2,4,16,QChar('0'))); + report_h = header_h + m_rxInfoDescriptor_h + m_txInfoDescriptor_h + rxInfoData_h + txInfoData_h; + //qDebug() << "Sending Report TX: "; + } else { + report_h = header_h + m_rxInfoDescriptor_h + rxInfoData_h; + //qDebug() << "Sending Report RX: "; + } + + report_h.replace("000Allll", "000A" + QString("%1").arg(report_h.length()/2,4,16,QChar('0'))); + QByteArray report = QByteArray::fromHex(report_h.toUtf8()); + + // Get IP address for pskreporter.info and send report via UDP + QHostInfo info = QHostInfo::fromName("report.pskreporter.info"); + m_udpSocket->writeDatagram(report,info.addresses().at(0),4739); +} + + diff --git a/psk_reporter.h b/psk_reporter.h index 79fc703f1..ce1b01969 100644 --- a/psk_reporter.h +++ b/psk_reporter.h @@ -1,42 +1,42 @@ -#ifndef PSK_REPORTER_H -#define PSK_REPORTER_H - -#include -#include -#include - -class PSK_Reporter : public QObject -{ - Q_OBJECT -public: - explicit PSK_Reporter(QObject *parent = 0); - void setLocalStation(QString call, QString grid, QString antenna, QString programInfo); - void addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time); - -signals: - -public slots: - void sendReport(); - -private: - QString m_header_h; - QString m_rxInfoDescriptor_h; - QString m_txInfoDescriptor_h; - QString m_randomId_h; - QString m_linkId_h; - - QString m_rxCall; - QString m_rxGrid; - QString m_rxAnt; - QString m_progId; - - QQueue< QHash > m_spotQueue; - - QUdpSocket *m_udpSocket; - - QTimer *reportTimer; - - int m_sequenceNumber; -}; - -#endif // PSK_REPORTER_H +#ifndef PSK_REPORTER_H +#define PSK_REPORTER_H + +#include +#include +#include + +class PSK_Reporter : public QObject +{ + Q_OBJECT +public: + explicit PSK_Reporter(QObject *parent = 0); + void setLocalStation(QString call, QString grid, QString antenna, QString programInfo); + void addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time); + +signals: + +public slots: + void sendReport(); + +private: + QString m_header_h; + QString m_rxInfoDescriptor_h; + QString m_txInfoDescriptor_h; + QString m_randomId_h; + QString m_linkId_h; + + QString m_rxCall; + QString m_rxGrid; + QString m_rxAnt; + QString m_progId; + + QQueue< QHash > m_spotQueue; + + QUdpSocket *m_udpSocket; + + QTimer *reportTimer; + + int m_sequenceNumber; +}; + +#endif // PSK_REPORTER_H diff --git a/rigclass.cpp b/rigclass.cpp index 51683ccae..b17f2000d 100644 --- a/rigclass.cpp +++ b/rigclass.cpp @@ -1,332 +1,332 @@ -/** - * \file src/rigclass.cc - * \brief Ham Radio Control Libraries C++ interface - * \author Stephane Fillod - * \date 2001-2003 - * - * Hamlib C++ interface is a frontend implementing wrapper functions. - */ - -/** - * - * Hamlib C++ bindings - main file - * Copyright (c) 2001-2003 by Stephane Fillod - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "rigclass.h" -#include -#include - -#define NUMTRIES 5 - -static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg); - -static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg) -{ - if (!rig || !rig->state.obj) - return -RIG_EINVAL; - -/* assert rig == ((Rig*)rig->state.obj).theRig */ - return ((Rig*)rig->state.obj)->FreqEvent(vfo, freq, arg); -} - -Rig::Rig() -{ - rig_set_debug_level( RIG_DEBUG_WARN); -} - -Rig::~Rig() { - theRig->state.obj = NULL; - rig_cleanup(theRig); - caps = NULL; -} - -int Rig::init(rig_model_t rig_model) -{ - int initOk; - - theRig = rig_init(rig_model); - if (!theRig) - initOk = false; - else - initOk = true; - - caps = theRig->caps; - theRig->callbacks.freq_event = &hamlibpp_freq_event; - theRig->state.obj = (rig_ptr_t)this; - - return initOk; -} - -int Rig::open(int n) { - m_hrd=false; - m_cmndr=false; - if(n<9900) { - if(n==-99999) return -1; //Silence compiler warning - return rig_open(theRig); - } - -#ifdef WIN32 // Ham radio Deluxe or Commander (Windows only) - if(n==9999) { - m_hrd=true; - bool bConnect=false; - bConnect = HRDInterfaceConnect(L"localhost",7809); - if(bConnect) { - const wchar_t* context=HRDInterfaceSendMessage(L"Get Context"); - m_context="[" + QString::fromWCharArray (context,-1) + "] "; - HRDInterfaceFreeString(context); - return 0; - } else { - m_hrd=false; - return -1; - } - } - if(n==9998) { - if(commanderSocket->state()==QAbstractSocket::ConnectedState) { - commanderSocket->abort(); - } - - if(commanderSocket->state()==QAbstractSocket::UnconnectedState) { - commanderSocket->connectToHost(QHostAddress::LocalHost, 52002); - if(!commanderSocket->waitForConnected(1000)) { - return -1; - } - } - QString t; - t="CmdGetFreq"; - QByteArray ba = t.toLocal8Bit(); - const char* buf=ba.data(); - commanderSocket->write(buf); - commanderSocket->waitForReadyRead(1000); - QByteArray reply=commanderSocket->read(128); - if(reply.indexOf("close(); - return 0; - } else -#endif - { - return rig_close(theRig); - } -} - -int Rig::setConf(const char *name, const char *val) -{ - return rig_set_conf(theRig, tokenLookup(name), val); -} - -int Rig::setFreq(freq_t freq, vfo_t vfo) { -#ifdef WIN32 // Ham Radio Deluxe (only on Windows) - if(m_hrd) { - QString t; - int nhz=(int)freq; - t=m_context + "Set Frequency-Hz " + QString::number(nhz); - const wchar_t* cmnd = (const wchar_t*) t.utf16(); - const wchar_t* result=HRDInterfaceSendMessage(cmnd); - QString t2=QString::fromWCharArray (result,-1); - HRDInterfaceFreeString(result); - if(t2=="OK") { - return 0; - } else { - return -1; - } - } else if(m_cmndr) { - QString t; - double f=0.001*freq; - t.sprintf("CmdSetFreq%10.3f",f); - QLocale locale; - t.replace(".",locale.decimalPoint()); - QByteArray ba = t.toLocal8Bit(); - const char* buf=ba.data(); - commanderSocket->write(buf); - commanderSocket->waitForBytesWritten(1000); - return 0; - } else -#endif - { - return rig_set_freq(theRig, vfo, freq); - } -} - -int Rig::setXit(shortfreq_t xit, vfo_t vfo) -{ - return rig_set_xit(theRig, vfo, xit); -} - -int Rig::setVFO(vfo_t vfo) -{ - return rig_set_vfo(theRig, vfo); -} - -vfo_t Rig::getVFO() -{ - vfo_t vfo; - rig_get_vfo(theRig, &vfo); - return vfo; -} - -int Rig::setSplitFreq(freq_t tx_freq, vfo_t vfo) { -#ifdef WIN32 // Ham Radio Deluxe only on Windows - if(m_hrd) { - QString t; - int nhz=(int)tx_freq; - t=m_context + "Set Frequency-Hz " + QString::number(nhz); - const wchar_t* cmnd = (const wchar_t*) t.utf16(); - const wchar_t* result=HRDInterfaceSendMessage(cmnd); - QString t2=QString::fromWCharArray (result,-1); - HRDInterfaceFreeString(result); - if(t2=="OK") { - return 0; - } else { - return -1; - } - } else if(m_cmndr) { - QString t; - double f=0.001*tx_freq; - t.sprintf("CmdSetTxFreq%10.3f",f); - QLocale locale; - t.replace(".",locale.decimalPoint()); - QByteArray ba = t.toLocal8Bit(); - const char* buf=ba.data(); - commanderSocket->write(buf); - commanderSocket->waitForBytesWritten(1000); - return 0; - } else -#endif - { - return rig_set_split_freq(theRig, vfo, tx_freq); - } -} - -freq_t Rig::getFreq(vfo_t vfo) -{ - freq_t freq; -#ifdef WIN32 // Ham Radio Deluxe (only on Windows) - if(m_hrd) { - const wchar_t* cmnd = (const wchar_t*) (m_context+"Get Frequency").utf16(); - const wchar_t* freqString=HRDInterfaceSendMessage(cmnd); - QString t2=QString::fromWCharArray (freqString,-1); - HRDInterfaceFreeString(freqString); - freq=t2.toDouble(); - return freq; - } else if(m_cmndr) { - QString t; - t="CmdGetFreq"; - QByteArray ba = t.toLocal8Bit(); - const char* buf=ba.data(); - commanderSocket->write(buf); - commanderSocket->waitForReadyRead(1000); - QByteArray reply=commanderSocket->read(128); - QString t2(reply); - if(t2.indexOf(""); - t2=t2.mid(i1+1).replace(",",""); - freq=1000.0*t2.toDouble(); - return freq; - } else { - return -1.0; - } - } else -#endif - { - freq=-1.0; - for(int i=0; i0) t="CmdTX"; - QByteArray ba = t.toLocal8Bit(); - const char* buf=ba.data(); - commanderSocket->write(buf); - commanderSocket->waitForBytesWritten(1000); - return 0; - } else -#endif - { - return rig_set_ptt(theRig, vfo, ptt); - } -} - -ptt_t Rig::getPTT(vfo_t vfo) -{ - ptt_t ptt; - rig_get_ptt(theRig, vfo, &ptt); - return ptt; -} - -token_t Rig::tokenLookup(const char *name) -{ - return rig_token_lookup(theRig, name); -} +/** + * \file src/rigclass.cc + * \brief Ham Radio Control Libraries C++ interface + * \author Stephane Fillod + * \date 2001-2003 + * + * Hamlib C++ interface is a frontend implementing wrapper functions. + */ + +/** + * + * Hamlib C++ bindings - main file + * Copyright (c) 2001-2003 by Stephane Fillod + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "rigclass.h" +#include +#include + +#define NUMTRIES 5 + +static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg); + +static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg) +{ + if (!rig || !rig->state.obj) + return -RIG_EINVAL; + +/* assert rig == ((Rig*)rig->state.obj).theRig */ + return ((Rig*)rig->state.obj)->FreqEvent(vfo, freq, arg); +} + +Rig::Rig() +{ + rig_set_debug_level( RIG_DEBUG_WARN); +} + +Rig::~Rig() { + theRig->state.obj = NULL; + rig_cleanup(theRig); + caps = NULL; +} + +int Rig::init(rig_model_t rig_model) +{ + int initOk; + + theRig = rig_init(rig_model); + if (!theRig) + initOk = false; + else + initOk = true; + + caps = theRig->caps; + theRig->callbacks.freq_event = &hamlibpp_freq_event; + theRig->state.obj = (rig_ptr_t)this; + + return initOk; +} + +int Rig::open(int n) { + m_hrd=false; + m_cmndr=false; + if(n<9900) { + if(n==-99999) return -1; //Silence compiler warning + return rig_open(theRig); + } + +#ifdef WIN32 // Ham radio Deluxe or Commander (Windows only) + if(n==9999) { + m_hrd=true; + bool bConnect=false; + bConnect = HRDInterfaceConnect(L"localhost",7809); + if(bConnect) { + const wchar_t* context=HRDInterfaceSendMessage(L"Get Context"); + m_context="[" + QString::fromWCharArray (context,-1) + "] "; + HRDInterfaceFreeString(context); + return 0; + } else { + m_hrd=false; + return -1; + } + } + if(n==9998) { + if(commanderSocket->state()==QAbstractSocket::ConnectedState) { + commanderSocket->abort(); + } + + if(commanderSocket->state()==QAbstractSocket::UnconnectedState) { + commanderSocket->connectToHost(QHostAddress::LocalHost, 52002); + if(!commanderSocket->waitForConnected(1000)) { + return -1; + } + } + QString t; + t="CmdGetFreq"; + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + commanderSocket->write(buf); + commanderSocket->waitForReadyRead(1000); + QByteArray reply=commanderSocket->read(128); + if(reply.indexOf("close(); + return 0; + } else +#endif + { + return rig_close(theRig); + } +} + +int Rig::setConf(const char *name, const char *val) +{ + return rig_set_conf(theRig, tokenLookup(name), val); +} + +int Rig::setFreq(freq_t freq, vfo_t vfo) { +#ifdef WIN32 // Ham Radio Deluxe (only on Windows) + if(m_hrd) { + QString t; + int nhz=(int)freq; + t=m_context + "Set Frequency-Hz " + QString::number(nhz); + const wchar_t* cmnd = (const wchar_t*) t.utf16(); + const wchar_t* result=HRDInterfaceSendMessage(cmnd); + QString t2=QString::fromWCharArray (result,-1); + HRDInterfaceFreeString(result); + if(t2=="OK") { + return 0; + } else { + return -1; + } + } else if(m_cmndr) { + QString t; + double f=0.001*freq; + t.sprintf("CmdSetFreq%10.3f",f); + QLocale locale; + t.replace(".",locale.decimalPoint()); + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + commanderSocket->write(buf); + commanderSocket->waitForBytesWritten(1000); + return 0; + } else +#endif + { + return rig_set_freq(theRig, vfo, freq); + } +} + +int Rig::setXit(shortfreq_t xit, vfo_t vfo) +{ + return rig_set_xit(theRig, vfo, xit); +} + +int Rig::setVFO(vfo_t vfo) +{ + return rig_set_vfo(theRig, vfo); +} + +vfo_t Rig::getVFO() +{ + vfo_t vfo; + rig_get_vfo(theRig, &vfo); + return vfo; +} + +int Rig::setSplitFreq(freq_t tx_freq, vfo_t vfo) { +#ifdef WIN32 // Ham Radio Deluxe only on Windows + if(m_hrd) { + QString t; + int nhz=(int)tx_freq; + t=m_context + "Set Frequency-Hz " + QString::number(nhz); + const wchar_t* cmnd = (const wchar_t*) t.utf16(); + const wchar_t* result=HRDInterfaceSendMessage(cmnd); + QString t2=QString::fromWCharArray (result,-1); + HRDInterfaceFreeString(result); + if(t2=="OK") { + return 0; + } else { + return -1; + } + } else if(m_cmndr) { + QString t; + double f=0.001*tx_freq; + t.sprintf("CmdSetTxFreq%10.3f",f); + QLocale locale; + t.replace(".",locale.decimalPoint()); + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + commanderSocket->write(buf); + commanderSocket->waitForBytesWritten(1000); + return 0; + } else +#endif + { + return rig_set_split_freq(theRig, vfo, tx_freq); + } +} + +freq_t Rig::getFreq(vfo_t vfo) +{ + freq_t freq; +#ifdef WIN32 // Ham Radio Deluxe (only on Windows) + if(m_hrd) { + const wchar_t* cmnd = (const wchar_t*) (m_context+"Get Frequency").utf16(); + const wchar_t* freqString=HRDInterfaceSendMessage(cmnd); + QString t2=QString::fromWCharArray (freqString,-1); + HRDInterfaceFreeString(freqString); + freq=t2.toDouble(); + return freq; + } else if(m_cmndr) { + QString t; + t="CmdGetFreq"; + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + commanderSocket->write(buf); + commanderSocket->waitForReadyRead(1000); + QByteArray reply=commanderSocket->read(128); + QString t2(reply); + if(t2.indexOf(""); + t2=t2.mid(i1+1).replace(",",""); + freq=1000.0*t2.toDouble(); + return freq; + } else { + return -1.0; + } + } else +#endif + { + freq=-1.0; + for(int i=0; i0) t="CmdTX"; + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + commanderSocket->write(buf); + commanderSocket->waitForBytesWritten(1000); + return 0; + } else +#endif + { + return rig_set_ptt(theRig, vfo, ptt); + } +} + +ptt_t Rig::getPTT(vfo_t vfo) +{ + ptt_t ptt; + rig_get_ptt(theRig, vfo, &ptt); + return ptt; +} + +token_t Rig::tokenLookup(const char *name) +{ + return rig_token_lookup(theRig, name); +} diff --git a/rigclass.h b/rigclass.h index 786f223db..77522129e 100644 --- a/rigclass.h +++ b/rigclass.h @@ -1,98 +1,98 @@ -/* - * Hamlib C++ bindings - API header - * Copyright (c) 2001-2002 by Stephane Fillod - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef _RIGCLASS_H -#define _RIGCLASS_H 1 - -#include -#include -#include -#include - -extern QTcpSocket* commanderSocket; - -class BACKEND_IMPEXP Rig { -private: - RIG* theRig; // Global ref. to the rig - bool m_hrd; - bool m_cmndr; - QString m_context; - - -protected: -public: - Rig(); - virtual ~Rig(); - - const struct rig_caps *caps; - - // Initialize rig - int init(rig_model_t rig_model); - - // This method open the communication port to the rig - int open(int n); - - // This method close the communication port to the rig - int close(void); - - int setConf(const char *name, const char *val); - token_t tokenLookup(const char *name); - - int setFreq(freq_t freq, vfo_t vfo = RIG_VFO_CURR); - freq_t getFreq(vfo_t vfo = RIG_VFO_CURR); - int setMode(rmode_t, pbwidth_t width = RIG_PASSBAND_NORMAL, vfo_t vfo = RIG_VFO_CURR); - rmode_t getMode(pbwidth_t&, vfo_t vfo = RIG_VFO_CURR); - int setVFO(vfo_t); - vfo_t getVFO(); - int setXit(shortfreq_t xit, vfo_t vfo); - int setSplitFreq(freq_t tx_freq, vfo_t vfo = RIG_VFO_CURR); - int setPTT (ptt_t ptt, vfo_t vfo = RIG_VFO_CURR); - ptt_t getPTT (vfo_t vfo = RIG_VFO_CURR); - - // callbacks available in your derived object - virtual int FreqEvent(vfo_t, freq_t, rig_ptr_t) const { - return RIG_OK; - } - virtual int ModeEvent(vfo_t, rmode_t, pbwidth_t, rig_ptr_t) const { - return RIG_OK; - } - virtual int VFOEvent(vfo_t, rig_ptr_t) const { - return RIG_OK; - } - virtual int PTTEvent(vfo_t, ptt_t, rig_ptr_t) const { - return RIG_OK; - } - virtual int DCDEvent(vfo_t, dcd_t, rig_ptr_t) const { - return RIG_OK; - } -}; - -#ifdef WIN32 -extern "C" { - bool HRDInterfaceConnect(const wchar_t *host, const ushort); - void HRDInterfaceDisconnect(); - bool HRDInterfaceIsConnected(); - wchar_t* HRDInterfaceSendMessage(const wchar_t *msg); - void HRDInterfaceFreeString(const wchar_t *lstring); -} -#endif - -#endif // _RIGCLASS_H +/* + * Hamlib C++ bindings - API header + * Copyright (c) 2001-2002 by Stephane Fillod + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _RIGCLASS_H +#define _RIGCLASS_H 1 + +#include +#include +#include +#include + +extern QTcpSocket* commanderSocket; + +class BACKEND_IMPEXP Rig { +private: + RIG* theRig; // Global ref. to the rig + bool m_hrd; + bool m_cmndr; + QString m_context; + + +protected: +public: + Rig(); + virtual ~Rig(); + + const struct rig_caps *caps; + + // Initialize rig + int init(rig_model_t rig_model); + + // This method open the communication port to the rig + int open(int n); + + // This method close the communication port to the rig + int close(void); + + int setConf(const char *name, const char *val); + token_t tokenLookup(const char *name); + + int setFreq(freq_t freq, vfo_t vfo = RIG_VFO_CURR); + freq_t getFreq(vfo_t vfo = RIG_VFO_CURR); + int setMode(rmode_t, pbwidth_t width = RIG_PASSBAND_NORMAL, vfo_t vfo = RIG_VFO_CURR); + rmode_t getMode(pbwidth_t&, vfo_t vfo = RIG_VFO_CURR); + int setVFO(vfo_t); + vfo_t getVFO(); + int setXit(shortfreq_t xit, vfo_t vfo); + int setSplitFreq(freq_t tx_freq, vfo_t vfo = RIG_VFO_CURR); + int setPTT (ptt_t ptt, vfo_t vfo = RIG_VFO_CURR); + ptt_t getPTT (vfo_t vfo = RIG_VFO_CURR); + + // callbacks available in your derived object + virtual int FreqEvent(vfo_t, freq_t, rig_ptr_t) const { + return RIG_OK; + } + virtual int ModeEvent(vfo_t, rmode_t, pbwidth_t, rig_ptr_t) const { + return RIG_OK; + } + virtual int VFOEvent(vfo_t, rig_ptr_t) const { + return RIG_OK; + } + virtual int PTTEvent(vfo_t, ptt_t, rig_ptr_t) const { + return RIG_OK; + } + virtual int DCDEvent(vfo_t, dcd_t, rig_ptr_t) const { + return RIG_OK; + } +}; + +#ifdef WIN32 +extern "C" { + bool HRDInterfaceConnect(const wchar_t *host, const ushort); + void HRDInterfaceDisconnect(); + bool HRDInterfaceIsConnected(); + wchar_t* HRDInterfaceSendMessage(const wchar_t *msg); + void HRDInterfaceFreeString(const wchar_t *lstring); +} +#endif + +#endif // _RIGCLASS_H diff --git a/signalmeter.cpp b/signalmeter.cpp index 7fb126d50..537b900f8 100644 --- a/signalmeter.cpp +++ b/signalmeter.cpp @@ -1,53 +1,53 @@ -// Simple bargraph dB meter -// Implemented by Edson Pereira PY2SDR -// -// Limits and geometry are hardcded for now. - -#include "signalmeter.h" - -SignalMeter::SignalMeter(QWidget *parent) : - QWidget(parent) -{ - resize(parent->size()); - - m_meter = new MeterWidget(this); - m_meter->setGeometry(10, 10, 10, 120); - - m_label = new QLabel(this); - m_label->setGeometry(10, 135, 20, 20); - - QLabel *dbLabel = new QLabel(this); - dbLabel->setText("dB"); - dbLabel->setGeometry(30, 135, 20, 20); -} - -SignalMeter::~SignalMeter() -{ - -} - -void SignalMeter::paintEvent( QPaintEvent * ) -{ - QPainter p; - p.begin(this); - p.drawLine(22, 10, 22, 130); - - for ( int i = 0; i <= 60; i += 10 ) { - p.drawLine(22, i*2 + 10, 25, i*2 + 10); - } - - for ( int i = 10; i < 60; i += 10 ) { - p.drawText(30, i*2 + 15, QString::number(60 - i)); - } -} - -void SignalMeter::setValue(int value) -{ - m_meter->setValue(value); - m_label->setText(QString::number(value)); -} - -void SignalMeter::resizeEvent(QResizeEvent *s) -{ - resize(s->size()); -} +// Simple bargraph dB meter +// Implemented by Edson Pereira PY2SDR +// +// Limits and geometry are hardcded for now. + +#include "signalmeter.h" + +SignalMeter::SignalMeter(QWidget *parent) : + QWidget(parent) +{ + resize(parent->size()); + + m_meter = new MeterWidget(this); + m_meter->setGeometry(10, 10, 10, 120); + + m_label = new QLabel(this); + m_label->setGeometry(10, 135, 20, 20); + + QLabel *dbLabel = new QLabel(this); + dbLabel->setText("dB"); + dbLabel->setGeometry(30, 135, 20, 20); +} + +SignalMeter::~SignalMeter() +{ + +} + +void SignalMeter::paintEvent( QPaintEvent * ) +{ + QPainter p; + p.begin(this); + p.drawLine(22, 10, 22, 130); + + for ( int i = 0; i <= 60; i += 10 ) { + p.drawLine(22, i*2 + 10, 25, i*2 + 10); + } + + for ( int i = 10; i < 60; i += 10 ) { + p.drawText(30, i*2 + 15, QString::number(60 - i)); + } +} + +void SignalMeter::setValue(int value) +{ + m_meter->setValue(value); + m_label->setText(QString::number(value)); +} + +void SignalMeter::resizeEvent(QResizeEvent *s) +{ + resize(s->size()); +} diff --git a/signalmeter.h b/signalmeter.h index bdf06a4d6..ea1aa6295 100644 --- a/signalmeter.h +++ b/signalmeter.h @@ -1,32 +1,32 @@ -#ifndef SIGNALMETER_H -#define SIGNALMETER_H - -#include -#include -#include - -class SignalMeter : public QWidget -{ - Q_OBJECT - -public: - explicit SignalMeter(QWidget *parent = 0); - ~SignalMeter(); - -public slots: - void setValue(int value); - -private: - MeterWidget *m_meter; - - QLabel *m_label; - - int m_signal; - int m_sigPeak; - -protected: - void paintEvent( QPaintEvent * ); - void resizeEvent(QResizeEvent *s); -}; - -#endif // SIGNALMETER_H +#ifndef SIGNALMETER_H +#define SIGNALMETER_H + +#include +#include +#include + +class SignalMeter : public QWidget +{ + Q_OBJECT + +public: + explicit SignalMeter(QWidget *parent = 0); + ~SignalMeter(); + +public slots: + void setValue(int value); + +private: + MeterWidget *m_meter; + + QLabel *m_label; + + int m_signal; + int m_sigPeak; + +protected: + void paintEvent( QPaintEvent * ); + void resizeEvent(QResizeEvent *s); +}; + +#endif // SIGNALMETER_H diff --git a/soundin.cpp b/soundin.cpp index 327e658b8..b2c2714e7 100644 --- a/soundin.cpp +++ b/soundin.cpp @@ -38,12 +38,15 @@ bool SoundInput::audioError () const return result; } -bool SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, QIODevice * sink) +bool SoundInput::start(QAudioDeviceInfo const& device, unsigned channels, int framesPerBuffer, QIODevice * sink) { + Q_ASSERT (0 < channels && channels < 3); + Q_ASSERT (sink); + stop(); QAudioFormat format (device.preferredFormat()); - format.setChannelCount (1); + format.setChannelCount (channels); format.setCodec ("audio/pcm"); format.setSampleRate (12000); format.setSampleType (QAudioFormat::SignedInt); diff --git a/soundin.h b/soundin.h index 05983ab98..660978882 100644 --- a/soundin.h +++ b/soundin.h @@ -32,7 +32,7 @@ Q_SIGNALS: public Q_SLOTS: // sink must exist from the start call to any following stop () call - bool start(QAudioDeviceInfo const&, int framesPerBuffer, QIODevice * sink); + bool start(QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink); void stop(); private: diff --git a/soundout.cpp b/soundout.cpp index a92f17bd2..d2a1b78d1 100644 --- a/soundout.cpp +++ b/soundout.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #if defined (WIN32) @@ -52,18 +53,15 @@ SoundOutput::SoundOutput (QIODevice * source) Q_ASSERT (source); } -void SoundOutput::startStream (QAudioDeviceInfo const& device) +void SoundOutput::startStream (QAudioDeviceInfo const& device, unsigned channels) { - if (!m_stream || device != m_currentDevice) + Q_ASSERT (0 < channels && channels < 3); + + if (!m_stream || device != m_currentDevice || channels != static_cast (m_stream->format ().channelCount ())) { QAudioFormat format (device.preferredFormat ()); -#ifdef UNIX - format.setChannelCount (2); -#else - format.setChannelCount (1); -#endif - + format.setChannelCount (channels); format.setCodec ("audio/pcm"); format.setSampleRate (48000); format.setSampleType (QAudioFormat::SignedInt); @@ -79,6 +77,7 @@ void SoundOutput::startStream (QAudioDeviceInfo const& device) m_stream.reset (new QAudioOutput (device, format, this)); audioError (); + m_stream->setVolume (m_volume); connect (m_stream.data(), &QAudioOutput::stateChanged, this, &SoundOutput::handleStateChanged); @@ -86,13 +85,13 @@ void SoundOutput::startStream (QAudioDeviceInfo const& device) } // - // This buffer size is critical since we are running in the GUI - // thread. If it is too short; high activity levels on the GUI can - // starve the audio buffer. On the other hand the Windows - // implementation seems to take the length of the buffer in time to - // stop the audio stream even if reset() is used. + // This buffer size is critical since for proper sound streaming. If + // it is too short; high activity levels on the machine can starve + // the audio buffer. On the other hand the Windows implementation + // seems to take the length of the buffer in time to stop the audio + // stream even if reset() is used. // - // 1 seconds seems a reasonable compromise except for Windows + // 2 seconds seems a reasonable compromise except for Windows // where things are probably broken. // // we have to set this before every start on the stream because the @@ -121,6 +120,31 @@ void SoundOutput::resume () } } +qreal SoundOutput::attenuation () const +{ + return -(10. * qLn (m_volume) / qLn (10.)); +} + +void SoundOutput::setAttenuation (qreal a) +{ + Q_ASSERT (0. <= a && a <= 99.); + m_volume = qPow (10., -a / 10.); + qDebug () << "SoundOut: attn = " << a << ", vol = " << m_volume; + if (m_stream) + { + m_stream->setVolume (m_volume); + } +} + +void SoundOutput::resetAttenuation () +{ + m_volume = 1.; + if (m_stream) + { + m_stream->setVolume (m_volume); + } +} + void SoundOutput::stopStream () { if (m_stream) diff --git a/soundout.h b/soundout.h index bdca53a3f..178b438c0 100644 --- a/soundout.h +++ b/soundout.h @@ -17,6 +17,7 @@ class SoundOutput : public QObject Q_OBJECT; Q_PROPERTY(bool running READ isRunning); + Q_PROPERTY(unsigned attenuation READ attenuation WRITE setAttenuation RESET resetAttenuation); private: Q_DISABLE_COPY (SoundOutput); @@ -26,12 +27,18 @@ class SoundOutput : public QObject ~SoundOutput (); bool isRunning() const {return m_active;} + qreal attenuation () const; - public Q_SLOTS: - void startStream (QAudioDeviceInfo const& device); + private Q_SLOTS: + /* private because we expect to run in a thread and don't want direct + C++ calls made, instead they must be invoked via the Qt + signal/slot mechanism which is thread safe */ + void startStream (QAudioDeviceInfo const& device, unsigned channels); void suspend (); void resume (); void stopStream (); + void setAttenuation (qreal); /* unsigned */ + void resetAttenuation (); /* to zero */ Q_SIGNALS: void error (QString message) const; @@ -49,6 +56,7 @@ private: QIODevice * m_source; bool volatile m_active; QAudioDeviceInfo m_currentDevice; + qreal m_volume; }; #endif diff --git a/widegraph.cpp b/widegraph.cpp index a58e4fe07..654280153 100644 --- a/widegraph.cpp +++ b/widegraph.cpp @@ -4,16 +4,20 @@ #define MAX_SCREENSIZE 2048 -WideGraph::WideGraph(QWidget *parent) : +WideGraph::WideGraph(QSettings * settings, QWidget *parent) : QDialog(parent), - ui(new Ui::WideGraph) + ui(new Ui::WideGraph), + m_settings (settings) { + installEventFilter (parent); + + setWindowTitle ("Wide Graph"); + setWindowFlags (Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint); + setMaximumWidth (MAX_SCREENSIZE); + setMaximumHeight (880); + ui->setupUi(this); - this->setWindowFlags(Qt::Dialog); - this->installEventFilter(parent); //Installing the filter ui->widePlot->setCursor(Qt::CrossCursor); - this->setMaximumWidth(MAX_SCREENSIZE); - this->setMaximumHeight(880); ui->widePlot->setMaximumHeight(800); ui->widePlot->m_bCurrent=false; @@ -23,38 +27,35 @@ WideGraph::WideGraph(QWidget *parent) : connect(ui->widePlot, SIGNAL(setFreq1(int,int)),this, SLOT(setFreq2(int,int))); - m_fMin=3000; - ui->fMinSpinBox->setValue(m_fMin); - //Restore user's settings - QString inifile(QApplication::applicationDirPath()); - inifile += "/wsjtx.ini"; - QSettings settings(inifile, QSettings::IniFormat); - - settings.beginGroup("WideGraph"); - ui->widePlot->setPlotZero(settings.value("PlotZero", 0).toInt()); - ui->widePlot->setPlotGain(settings.value("PlotGain", 0).toInt()); + m_settings->beginGroup("WideGraph"); + restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ()); + ui->widePlot->setPlotZero(m_settings->value("PlotZero", 0).toInt()); + ui->widePlot->setPlotGain(m_settings->value("PlotGain", 0).toInt()); ui->zeroSpinBox->setValue(ui->widePlot->getPlotZero()); ui->gainSpinBox->setValue(ui->widePlot->getPlotGain()); - int n = settings.value("FreqSpan",2).toInt(); - int w = settings.value("PlotWidth",1000).toInt(); + int n = m_settings->value("FreqSpan",2).toInt(); + int w = m_settings->value("PlotWidth",1000).toInt(); ui->widePlot->m_w=w; ui->freqSpanSpinBox->setValue(n); ui->widePlot->setNSpan(n); - m_waterfallAvg = settings.value("WaterfallAvg",5).toInt(); + m_waterfallAvg = m_settings->value("WaterfallAvg",5).toInt(); ui->waterfallAvgSpinBox->setValue(m_waterfallAvg); - ui->widePlot->m_bCurrent=settings.value("Current",false).toBool(); - ui->widePlot->m_bCumulative=settings.value("Cumulative",true).toBool(); + ui->widePlot->m_bCurrent=m_settings->value("Current",false).toBool(); + ui->widePlot->m_bCumulative=m_settings->value("Cumulative",true).toBool(); if(ui->widePlot->m_bCurrent) ui->spec2dComboBox->setCurrentIndex(0); if(ui->widePlot->m_bCumulative) ui->spec2dComboBox->setCurrentIndex(1); - int nbpp=settings.value("BinsPerPixel",2).toInt(); + int nbpp=m_settings->value("BinsPerPixel",2).toInt(); ui->widePlot->setBinsPerPixel(nbpp); - m_slope=settings.value("Slope",0.0).toDouble(); + m_slope=m_settings->value("Slope",0.0).toDouble(); ui->slopeSpinBox->setValue(m_slope); - ui->widePlot->setStartFreq(settings.value("StartFreq",0).toInt()); + ui->widePlot->setStartFreq(m_settings->value("StartFreq",0).toInt()); ui->fStartSpinBox->setValue(ui->widePlot->startFreq()); - m_waterfallPalette=settings.value("WaterfallPalette","Default").toString(); - settings.endGroup(); + m_waterfallPalette=m_settings->value("WaterfallPalette","Default").toString(); + int m_fMin = m_settings->value ("fMin", 2500).toInt (); + ui->fMinSpinBox->setValue (m_fMin); + setRxRange (m_fMin); + m_settings->endGroup(); QDir recoredDir("Palettes"); QStringList allFiles = recoredDir.entryList(QDir::NoDotAndDotDot | @@ -73,32 +74,33 @@ WideGraph::WideGraph(QWidget *parent) : readPalette("Palettes/" + m_waterfallPalette + ".pal"); } -WideGraph::~WideGraph() +WideGraph::~WideGraph () { - saveSettings(); - delete ui; +} + +void WideGraph::closeEvent (QCloseEvent * e) +{ + saveSettings (); + QDialog::closeEvent (e); } void WideGraph::saveSettings() { - //Save user's settings - QString inifile(QApplication::applicationDirPath()); - inifile += "/wsjtx.ini"; - QSettings settings(inifile, QSettings::IniFormat); - - settings.beginGroup("WideGraph"); - settings.setValue("PlotZero",ui->widePlot->m_plotZero); - settings.setValue("PlotGain",ui->widePlot->m_plotGain); - settings.setValue("PlotWidth",ui->widePlot->plotWidth()); - settings.setValue("FreqSpan",ui->freqSpanSpinBox->value()); - settings.setValue("WaterfallAvg",ui->waterfallAvgSpinBox->value()); - settings.setValue("Current",ui->widePlot->m_bCurrent); - settings.setValue("Cumulative",ui->widePlot->m_bCumulative); - settings.setValue("BinsPerPixel",ui->widePlot->binsPerPixel()); - settings.setValue("Slope",m_slope); - settings.setValue("StartFreq",ui->widePlot->startFreq()); - settings.setValue("WaterfallPalette",m_waterfallPalette); - settings.endGroup(); + m_settings->beginGroup ("WideGraph"); + m_settings->setValue ("geometry", saveGeometry ()); + m_settings->setValue ("PlotZero", ui->widePlot->m_plotZero); + m_settings->setValue ("PlotGain", ui->widePlot->m_plotGain); + m_settings->setValue ("PlotWidth", ui->widePlot->plotWidth ()); + m_settings->setValue ("FreqSpan", ui->freqSpanSpinBox->value ()); + m_settings->setValue ("WaterfallAvg", ui->waterfallAvgSpinBox->value ()); + m_settings->setValue ("Current", ui->widePlot->m_bCurrent); + m_settings->setValue ("Cumulative", ui->widePlot->m_bCumulative); + m_settings->setValue ("BinsPerPixel", ui->widePlot->binsPerPixel ()); + m_settings->setValue ("Slope", m_slope); + m_settings->setValue ("StartFreq", ui->widePlot->startFreq ()); + m_settings->setValue ("WaterfallPalette", m_waterfallPalette); + m_settings->setValue ("Fmin", m_fMin); + m_settings->endGroup (); } void WideGraph::dataSink2(float s[], float df3, int ihsym, @@ -238,13 +240,6 @@ int WideGraph::getFmax() return n; } -void WideGraph::setFmin(int n) -{ - m_fMin = n; - ui->fMinSpinBox->setValue(n); - setRxRange(m_fMin); -} - double WideGraph::fGreen() { return ui->widePlot->fGreen(); diff --git a/widegraph.h b/widegraph.h index 39bd4119e..695aca373 100644 --- a/widegraph.h +++ b/widegraph.h @@ -1,88 +1,93 @@ -#ifndef WIDEGRAPH_H -#define WIDEGRAPH_H -#include - -namespace Ui { - class WideGraph; -} - -class WideGraph : public QDialog -{ - Q_OBJECT - -public: - explicit WideGraph(QWidget *parent = 0); - ~WideGraph(); - - void dataSink2(float s[], float df3, int ihsym, int ndiskdata); - void setRxFreq(int n); - int rxFreq(); - int nSpan(); - int nStartFreq(); - int getFmin(); - int getFmax(); - float fSpan(); - void saveSettings(); - void setRxRange(int fMin); - void setFmin(int n); - void setFsample(int n); - void setPeriod(int ntrperiod, int nsps); - void setTxFreq(int n); - void setMode(QString mode); - void setModeTx(QString modeTx); - void setSlope(double d); - void setLockTxFreq(bool b); - double getSlope(); - double fGreen(); - void readPalette(QString fileName); - - qint32 m_rxFreq; - qint32 m_txFreq; - -signals: - void freezeDecode2(int n); - void f11f12(int n); - void setXIT2(int n); - void setFreq3(int rxFreq, int txFreq); - -public slots: - void wideFreezeDecode(int n); - void setFreq2(int rxFreq, int txFreq); - void setDialFreq(double d); - -protected: - virtual void keyPressEvent( QKeyEvent *e ); - -private slots: - void on_waterfallAvgSpinBox_valueChanged(int arg1); - void on_freqSpanSpinBox_valueChanged(int arg1); - void on_zeroSpinBox_valueChanged(int arg1); - void on_gainSpinBox_valueChanged(int arg1); - void on_spec2dComboBox_currentIndexChanged(const QString &arg1); - void on_fMinSpinBox_valueChanged(int n); - void on_slopeSpinBox_valueChanged(double d); - void on_fStartSpinBox_valueChanged(int n); - void on_paletteComboBox_activated(const QString &palette); - -private: - double m_slope; - double m_dialFreq; - - qint32 m_waterfallAvg; - qint32 m_fSample; - qint32 m_TRperiod; - qint32 m_nsps; - qint32 m_ntr0; - qint32 m_fMin; - qint32 m_fMax; - - bool m_lockTxFreq; - - QString m_mode; - QString m_modeTx; - QString m_waterfallPalette; - - Ui::WideGraph *ui; -}; - -#endif // WIDEGRAPH_H +#ifndef WIDEGRAPH_H +#define WIDEGRAPH_H + +#include +#include + +namespace Ui { + class WideGraph; +} + +class QSettings; + +class WideGraph : public QDialog +{ + Q_OBJECT + +public: + explicit WideGraph(QSettings *, QWidget *parent = 0); + ~WideGraph (); + + void dataSink2(float s[], float df3, int ihsym, int ndiskdata); + void setRxFreq(int n); + int rxFreq(); + int nSpan(); + int nStartFreq(); + int getFmin(); + int getFmax(); + float fSpan(); + void saveSettings(); + void setRxRange(int fMin); + void setFsample(int n); + void setPeriod(int ntrperiod, int nsps); + void setTxFreq(int n); + void setMode(QString mode); + void setModeTx(QString modeTx); + void setSlope(double d); + void setLockTxFreq(bool b); + double getSlope(); + double fGreen(); + void readPalette(QString fileName); + +signals: + void freezeDecode2(int n); + void f11f12(int n); + void setXIT2(int n); + void setFreq3(int rxFreq, int txFreq); + +public slots: + void wideFreezeDecode(int n); + void setFreq2(int rxFreq, int txFreq); + void setDialFreq(double d); + +protected: + virtual void keyPressEvent( QKeyEvent *e ); + void closeEvent (QCloseEvent *); + +private slots: + void on_waterfallAvgSpinBox_valueChanged(int arg1); + void on_freqSpanSpinBox_valueChanged(int arg1); + void on_zeroSpinBox_valueChanged(int arg1); + void on_gainSpinBox_valueChanged(int arg1); + void on_spec2dComboBox_currentIndexChanged(const QString &arg1); + void on_fMinSpinBox_valueChanged(int n); + void on_slopeSpinBox_valueChanged(double d); + void on_fStartSpinBox_valueChanged(int n); + void on_paletteComboBox_activated(const QString &palette); + +private: + QScopedPointer ui; + QSettings * m_settings; + + qint32 m_rxFreq; + qint32 m_txFreq; + + double m_slope; + double m_dialFreq; + + qint32 m_waterfallAvg; + qint32 m_fSample; + qint32 m_TRperiod; + qint32 m_nsps; + qint32 m_ntr0; + qint32 m_fMin; + qint32 m_fMax; + + bool m_lockTxFreq; + + QString m_mode; + QString m_modeTx; + QString m_waterfallPalette; +}; + +#endif // WIDEGRAPH_H diff --git a/wsjtx.pro b/wsjtx.pro index 737dc8016..1570f44f5 100644 --- a/wsjtx.pro +++ b/wsjtx.pro @@ -67,7 +67,7 @@ SOURCES += killbyname.cpp HEADERS += mainwindow.h plotter.h soundin.h soundout.h \ about.h devsetup.h widegraph.h getfile.h \ commons.h sleep.h displaytext.h logqso.h \ - Detector.hpp Modulator.hpp psk_reporter.h rigclass.h \ + AudioDevice.hpp Detector.hpp Modulator.hpp psk_reporter.h rigclass.h \ signalmeter.h \ meterwidget.h \ logbook/logbook.h \