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 \