mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-24 17:08:36 -05:00
Remote input/sink implemented remote control. Implements #1074
This commit is contained in:
parent
1d2187d059
commit
58a9b2996d
Binary file not shown.
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 43 KiB |
Binary file not shown.
@ -10,7 +10,7 @@ Please note that there is no provision for handling out of sync UDP blocks. It i
|
||||
|
||||
The remote SDRangel instance that sends the data stream is controlled via its REST API using a separate control software for example [SDRangelcli](https://github.com/f4exb/sdrangelcli)
|
||||
|
||||
A sample size conversion takes place if the stream sample size sent by the remote instance and the Rx sample size of the local instance do not match (i.e. 16 to 24 bits or 24 to 16 bits). Best performance is obtained when both instances use the same sample size.
|
||||
A sample size conversion takes place if the stream sample size sent by the remote instance and the Rx sample size of the local instance do not match (i.e. 8, 16 to 24 bits or 8, 24 to 16 bits). Best performance is obtained when the stream sample size matches the instance sample size.
|
||||
|
||||
<h2>Build</h2>
|
||||
|
||||
@ -35,22 +35,54 @@ This is the center frequency in Hz sent in the meta data from the remote SDRange
|
||||
|
||||
Stream I/Q sample rate in kS/s
|
||||
|
||||
<h3>4: Auto correction options and stream status</h3>
|
||||
<h3>4: Set remote device center frequency</h3>
|
||||
|
||||
Uses the API at the address and port specified in (12) to control the remote device center frequency (kHz)
|
||||
|
||||
<h3>5: Remote sink channel decimation factor</h3>
|
||||
|
||||
The remote device baseband can be decimated in the remote sink channel and its center can be selected with (8). The resulting sample rate of the I/Q stream sent over the network is the remote device baseband sample rate divided by this value. The value is displayed in (3).
|
||||
|
||||
It uses the API at the address and port specified in (12) to control the remote sink channel.
|
||||
|
||||
<h3>6: Remote sink half band filters chain sequence</h3>
|
||||
|
||||
This string represents the sequence of half-band filters used in the decimation from device baseband to resulting I/Q stream. Each character represents a filter type:
|
||||
|
||||
- **L**: lower half-band
|
||||
- **H**: higher half-band
|
||||
- **C**: centered
|
||||
|
||||
<h3>7: Remote sink center frequency shift</h3>
|
||||
|
||||
This is the shift of the remote sink channel center frequency from the remte device center frequency. Its value is driven by the remote device sample rate, the decimation (5) and the filter chain sequence (8).
|
||||
|
||||
<h3>8: Remote sink half-band filter chain sequence</h3>
|
||||
|
||||
The slider moves the remote sink channel center frequency roughly from the lower to the higher frequency in the remote device baseband. The number on the right represents the filter sequence as the decimal value of a base 3 number. Each base 3 digit represents the filter type and its sequence from MSB to LSB in the filter chain:
|
||||
|
||||
- **0**: lower half-band
|
||||
- **1**: centered
|
||||
- **2**: higher half-band
|
||||
|
||||
It uses the API at the address and port specified in (12) to control the remote sink channel.
|
||||
|
||||
<h3>9: Auto correction options and stream status</h3>
|
||||
|
||||
![SDR Remote input stream GUI](../../../doc/img/RemoteInput_plugin_02.png)
|
||||
|
||||
<h4>4.1: Auto correction options</h4>
|
||||
<h4>9.1: Auto correction options</h4>
|
||||
|
||||
These buttons control the local DSP auto correction options:
|
||||
|
||||
- **DC**: auto remove DC component
|
||||
- **IQ**: auto make I/Q balance
|
||||
|
||||
<h4>4.2: Receive buffer length</h4>
|
||||
<h4>9.2: Receive buffer length</h4>
|
||||
|
||||
This is the main buffer (writes from UDP / reads from DSP engine) length in units of time (seconds). As read and write pointers are normally about half the buffer apart the nominal delay introduced by the buffer is the half of this value.
|
||||
|
||||
<h4>4.3: Main buffer R/W pointers positions</h4>
|
||||
<h4>9.3: Main buffer R/W pointers positions</h4>
|
||||
|
||||
Read and write pointers should always be a half buffer distance buffer apart. This is the difference in percent of the main buffer size from this ideal position.
|
||||
|
||||
@ -59,11 +91,11 @@ Read and write pointers should always be a half buffer distance buffer apart. Th
|
||||
|
||||
This corresponds to the value shown in the gauges above (9)
|
||||
|
||||
<h4>4.4: Date/time</h4>
|
||||
<h4>9.4: Date/time</h4>
|
||||
|
||||
This is the current timestamp of the block of data sent from the receiver. It is refreshed about every second. The plugin tries to take into account the buffer that is used between the data received from the network and the data effectively used by the system however this may not be extremely accurate. It is based on the timestamps sent from the Remote sink channel at the other hand that does not take into account its own buffers.
|
||||
|
||||
<h3>5: Main buffer R/W pointers gauge</h3>
|
||||
<h3>10: Main buffer R/W pointers gauge</h3>
|
||||
|
||||
There are two gauges separated by a dot in the center. Ideally these gauges should not display any value thus read and write pointers are always half a buffer apart. However due to the fact that a whole frame is reconstructed at once up to ~10% variation is normal and should appear on the left gauge (write leads).
|
||||
|
||||
@ -72,15 +104,15 @@ There are two gauges separated by a dot in the center. Ideally these gauges shou
|
||||
|
||||
The system tries to compensate read / write unbalance however at start or when a large stream disruption has occurred a delay of a few tens of seconds is necessary before read / write reaches equilibrium.
|
||||
|
||||
<h3>6: Data stream status</h3>
|
||||
<h3>11: Data stream status</h3>
|
||||
|
||||
![SDR Remote input stream GUI](../../../doc/img/RemoteInput_plugin_04.png)
|
||||
|
||||
<h4>6.1: Sample size</h4>
|
||||
<h4>11.1: Sample size</h4>
|
||||
|
||||
This is the size in bits of a I or Q sample sent in the stream by the remote server.
|
||||
|
||||
<h4>6.2: Total number of frames and number of FEC blocks</h4>
|
||||
<h4>11.2: Total number of frames and number of FEC blocks</h4>
|
||||
|
||||
This is the total number of frames and number of FEC blocks separated by a slash '/' as sent in the meta data block thus acknowledged by the remote server. When you set the number of FEC blocks with (4.1) the effect may not be immediate and this information can be used to monitor when it gets effectively set in the remote server.
|
||||
|
||||
@ -88,7 +120,7 @@ A frame consists of 128 data blocks (1 meta data block followed by 127 I/Q data
|
||||
|
||||
Using the Cauchy MDS block erasure correction ensures that if at least the number of data blocks (128) is received per complete frame then all lost blocks in any position can be restored. For example if 8 FEC blocks are used then 136 blocks are transmitted per frame. If only 130 blocks (128 or greater) are received then data can be recovered. If only 127 blocks (or less) are received then none of the lost blocks can be recovered.
|
||||
|
||||
<h4>6.3: Stream status</h4>
|
||||
<h4>11.3: Stream status</h4>
|
||||
|
||||
The color of the icon indicates stream status:
|
||||
|
||||
@ -96,82 +128,82 @@ The color of the icon indicates stream status:
|
||||
- No color: some original blocks were reconstructed from FEC blocks for some frames during the last polling timeframe (ex: between 128 and 135)
|
||||
- Red: some original blocks were definitely lost for some frames during the last polling timeframe (ex: less than 128)
|
||||
|
||||
<h4>6.4: Minimum total number of blocks per frame</h4>
|
||||
<h4>11.4: Minimum total number of blocks per frame</h4>
|
||||
|
||||
This is the minimum total number of blocks per frame during the last polling period. If all blocks were received for all frames then this number is the nominal number of original blocks plus FEC blocks (Green lock icon). In our example this is 128+8 = 136.
|
||||
|
||||
If this number falls below 128 then some blocks are definitely lost and the lock lights in red.
|
||||
|
||||
<h4>6.5: Maximum number of FEC blocks used by frame</h4>
|
||||
<h4>11.5: Maximum number of FEC blocks used by frame</h4>
|
||||
|
||||
Maximum number of FEC blocks used for original blocks recovery during the last polling timeframe. Ideally this should be 0 when no blocks are lost but the system is able to correct lost blocks up to the nominal number of FEC blocks (Neutral lock icon).
|
||||
|
||||
<h4>6.6: Reset events counters</h4>
|
||||
<h4>11.6: Reset events counters</h4>
|
||||
|
||||
This push button can be used to reset the events counters (4.7 and 4.8) and reset the event counts timer (4.9)
|
||||
This push button can be used to reset the events counters (9.7 and 9.8) and reset the event counts timer (9.9)
|
||||
|
||||
<h4>6.7: Unrecoverable error events counter</h4>
|
||||
<h4>11.7: Unrecoverable error events counter</h4>
|
||||
|
||||
This counter counts the unrecoverable error conditions found (i.e. 4.4 lower than 128) since the last counters reset.
|
||||
This counter counts the unrecoverable error conditions found (i.e. 9.4 lower than 128) since the last counters reset.
|
||||
|
||||
<h4>6.8: Recoverable error events counter</h4>
|
||||
<h4>11.8: Recoverable error events counter</h4>
|
||||
|
||||
This counter counts the unrecoverable error conditions found (i.e. 4.4 between 128 and 128 plus the number of FEC blocks) since the last counters reset.
|
||||
This counter counts the unrecoverable error conditions found (i.e. 9.4 between 128 and 128 plus the number of FEC blocks) since the last counters reset.
|
||||
|
||||
<h4>6.9: events counters timer</h4>
|
||||
<h4>11.9: events counters timer</h4>
|
||||
|
||||
This HH:mm:ss time display shows the time since the reset events counters button (4.6) was pushed.
|
||||
This HH:mm:ss time display shows the time since the reset events counters button (9.6) was pushed.
|
||||
|
||||
<h3>7: Remote server test</h3>
|
||||
<h3>12: Remote server test</h3>
|
||||
|
||||
Test remote connection with its API.
|
||||
|
||||
![SDR Remote input stream GUI](../../../doc/img/RemoteInput_plugin_05.png)
|
||||
|
||||
<h4>7.1: Remote connection indicator</h4>
|
||||
<h4>12.1: Remote connection indicator</h4>
|
||||
|
||||
The "Remote" label is lit in green when the connection is successful
|
||||
|
||||
<h4>7.2: API IP address</h4>
|
||||
<h4>12.2: API IP address</h4>
|
||||
|
||||
IP address of the remote SDRangel instance REST API
|
||||
|
||||
<h4>7.3: API port</h4>
|
||||
<h4>12.3: API port</h4>
|
||||
|
||||
Port of the remote SDRangel instance REST API
|
||||
|
||||
<h4>7.4: Get information button</h4>
|
||||
<h4>12.4: Get information button</h4>
|
||||
|
||||
When the return key is hit within the address (5.2) or port (5.3) the changes are effective immediately. You can also use this button to set again these values. Clicking on this button will send a request to the API to get the remote SDRangel instance information that is displayed in the API message box (8)
|
||||
When the return key is hit within the address (10.2) or port (10.3) the changes are effective immediately. You can also use this button to set again these values. Clicking on this button will send a request to the API to get the remote SDRangel instance information that is displayed in the API message box (13)
|
||||
|
||||
<h3>8: Local network interface address and port for data reception</h3>
|
||||
<h3>13: Local network interface address and port for data reception</h3>
|
||||
|
||||
![SDR Remote source input stream GUI](../../../doc/img/RemoteInput_plugin_06.png)
|
||||
|
||||
<h4>8.1: Interface IP address</h4>
|
||||
<h4>13.1: Interface IP address</h4>
|
||||
|
||||
IP address of the local network interface the remote SDRangel instance sends the data to. Effective when the validation button (8.3) is pressed.
|
||||
IP address of the local network interface the remote SDRangel instance sends the data to. Effective when the validation button (13.3) is pressed.
|
||||
|
||||
<h4>8.2: Interface port</h4>
|
||||
<h4>13.2: Interface port</h4>
|
||||
|
||||
Local port the remote SDRangel instance sends the data to. Effective when the validation button (8.3) is pressed.
|
||||
Local port the remote SDRangel instance sends the data to. Effective when the validation button (13.3) is pressed.
|
||||
|
||||
<h4>8.3: Validation button</h4>
|
||||
<h4>13.3: Validation button</h4>
|
||||
|
||||
When the return key is hit within the interface address (8.2), port (8.3), multicast group address (10) and multicast group join/leave (9) the changes of parameters for data reception are ready for commit and this button turns green. You then push this button to commit the changes.
|
||||
When the return key is hit within the interface address (13.2), port (13.3), multicast group address (15) and multicast group join/leave (14) the changes of parameters for data reception are ready for commit and this button turns green. You then push this button to commit the changes.
|
||||
|
||||
<h3>9: Join or leave multicast group</h3>
|
||||
<h3>14: Join or leave multicast group</h3>
|
||||
|
||||
Use this toggle button to join or leave the multicast group which address is specified next (10). Effective when the validation button (8.3) is pressed.
|
||||
Use this toggle button to join or leave the multicast group which address is specified next (15). Effective when the validation button (13.3) is pressed.
|
||||
|
||||
<h3>10: Multicast group address</h3>
|
||||
<h3>15: Multicast group address</h3>
|
||||
|
||||
This is the address of the multicast group. Effective when the validation button (8.3) is pressed.
|
||||
This is the address of the multicast group. Effective when the validation button (13.3) is pressed.
|
||||
|
||||
<h3>11: Status message</h3>
|
||||
<h3>16: Status message</h3>
|
||||
|
||||
The API status is displayed in this box. It shows "API OK" when the connection is successful and reply is OK
|
||||
|
||||
<h3>12: Remote information</h3>
|
||||
<h3>17: Remote information</h3>
|
||||
|
||||
This is the information returned by the remote when connection with its API is successful
|
||||
|
@ -60,7 +60,6 @@ RemoteInput::RemoteInput(DeviceAPI *deviceAPI) :
|
||||
m_sampleFifo.setSize(m_sampleRate * 8);
|
||||
m_remoteInputUDPHandler = new RemoteInputUDPHandler(&m_sampleFifo, m_deviceAPI);
|
||||
m_remoteInputUDPHandler->setMessageQueueToInput(&m_inputMessageQueue);
|
||||
connect(m_remoteInputUDPHandler, SIGNAL(metaChanged()), this, SLOT(handleMetaChanged()));
|
||||
|
||||
m_deviceAPI->setNbSourceStreams(1);
|
||||
|
||||
@ -164,19 +163,31 @@ bool RemoteInput::isStreaming() const
|
||||
|
||||
bool RemoteInput::handleMessage(const Message& message)
|
||||
{
|
||||
if (RemoteInputUDPHandler::MsgReportSampleRateChange::match(message))
|
||||
if (RemoteInputUDPHandler::MsgReportMetaDataChange::match(message))
|
||||
{
|
||||
RemoteInputUDPHandler::MsgReportSampleRateChange& notif = (RemoteInputUDPHandler::MsgReportSampleRateChange&) message;
|
||||
int sampleRate = notif.getSampleRate();
|
||||
qDebug() << "RemoteInput::handleMessage:" << message.getIdentifier();
|
||||
RemoteInputUDPHandler::MsgReportMetaDataChange& notif = (RemoteInputUDPHandler::MsgReportMetaDataChange&) message;
|
||||
m_currentMeta = notif.getMetaData();
|
||||
int sampleRate = m_currentMeta.m_sampleRate;
|
||||
|
||||
if (sampleRate != m_sampleRate)
|
||||
{
|
||||
qDebug("RemoteInput::handleMessage: RemoteInputUDPHandler::MsgReportSampleRateChange: %d", sampleRate);
|
||||
qDebug("RemoteInput::handleMessage: RemoteInputUDPHandler::MsgReportMetaDataChange: new sampleRate: %d", sampleRate);
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
m_sampleFifo.setSize(sampleRate * 8);
|
||||
m_sampleRate = sampleRate;
|
||||
}
|
||||
|
||||
m_currentMeta = m_remoteInputUDPHandler->getCurrentMeta();
|
||||
QString getSettingsURL= QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
.arg(m_settings.m_apiAddress)
|
||||
.arg(m_settings.m_apiPort)
|
||||
.arg(m_currentMeta.m_deviceIndex)
|
||||
.arg(m_currentMeta.m_channelIndex);
|
||||
|
||||
m_networkRequest.setUrl(QUrl(getSettingsURL));
|
||||
m_networkManager->get(m_networkRequest);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgStartStop::match(message))
|
||||
@ -218,6 +229,7 @@ bool RemoteInput::handleMessage(const Message& message)
|
||||
}
|
||||
else if (MsgRequestFixedData::match(message))
|
||||
{
|
||||
qDebug() << "RemoteInput::handleMessage:" << message.getIdentifier();
|
||||
QString reportURL;
|
||||
|
||||
reportURL = QString("http://%1:%2/sdrangel")
|
||||
@ -701,20 +713,4 @@ void RemoteInput::analyzeRemoteChannelSettingsReply(const QJsonObject& jsonObjec
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteInput::getRemoteChannelSettings()
|
||||
{
|
||||
QString getSettingsURL= QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
.arg(m_settings.m_apiAddress)
|
||||
.arg(m_settings.m_apiPort)
|
||||
.arg(m_currentMeta.m_deviceIndex)
|
||||
.arg(m_currentMeta.m_channelIndex);
|
||||
|
||||
m_networkRequest.setUrl(QUrl(getSettingsURL));
|
||||
m_networkManager->get(m_networkRequest);
|
||||
}
|
||||
|
||||
void RemoteInput::handleMetaChanged()
|
||||
{
|
||||
m_currentMeta = m_remoteInputUDPHandler->getCurrentMeta();
|
||||
getRemoteChannelSettings();
|
||||
}
|
||||
|
@ -419,13 +419,11 @@ private:
|
||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const RemoteInputSettings& settings, bool force);
|
||||
void webapiReverseSendStartStop(bool start);
|
||||
void getRemoteChannelSettings();
|
||||
void analyzeRemoteChannelSettingsReply(const QJsonObject& jsonObject);
|
||||
void analyzeInstanceSummaryReply(const QJsonObject& jsonObject);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void handleMetaChanged();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_REMOTEINPUT_H
|
||||
|
@ -84,6 +84,7 @@ RemoteInputGui::RemoteInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
m_statusTimer.start(500);
|
||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||
connect(&m_remoteUpdateTimer, SIGNAL(timeout()), this, SLOT(updateRemote()));
|
||||
|
||||
m_sampleSource = (RemoteInput*) m_deviceUISet->m_deviceAPI->getSampleSource();
|
||||
|
||||
@ -351,19 +352,16 @@ void RemoteInputGui::applyPosition()
|
||||
|
||||
void RemoteInputGui::applyRemoteSettings()
|
||||
{
|
||||
if (m_doApplySettings)
|
||||
{
|
||||
qDebug() << "RemoteInputGui::applyRemoteSettings";
|
||||
RemoteInput::MsgConfigureRemoteChannel* message =
|
||||
RemoteInput::MsgConfigureRemoteChannel::create(m_remoteChannelSettings);
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
if (!m_remoteUpdateTimer.isActive()) {
|
||||
m_remoteUpdateTimer.start(100);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteInputGui::sendSettings()
|
||||
{
|
||||
if(!m_updateTimer.isActive())
|
||||
if (!m_updateTimer.isActive()) {
|
||||
m_updateTimer.start(100);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteInputGui::on_remoteDeviceFrequency_changed(quint64 value)
|
||||
@ -615,6 +613,18 @@ void RemoteInputGui::updateHardware()
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteInputGui::updateRemote()
|
||||
{
|
||||
if (m_doApplySettings)
|
||||
{
|
||||
qDebug() << "RemoteInputGui::updateRemote";
|
||||
RemoteInput::MsgConfigureRemoteChannel* message =
|
||||
RemoteInput::MsgConfigureRemoteChannel::create(m_remoteChannelSettings);
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
m_remoteUpdateTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteInputGui::updateStatus()
|
||||
{
|
||||
if (m_sampleSource->isStreaming())
|
||||
|
@ -61,6 +61,7 @@ private:
|
||||
int m_streamSampleRate; //!< Sample rate of received stream
|
||||
quint64 m_streamCenterFrequency; //!< Center frequency of received stream
|
||||
QTimer m_updateTimer;
|
||||
QTimer m_remoteUpdateTimer;
|
||||
QTimer m_statusTimer;
|
||||
int m_lastEngineState;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
@ -134,6 +135,7 @@ private slots:
|
||||
void on_startStop_toggled(bool checked);
|
||||
void on_eventCountsReset_clicked(bool checked);
|
||||
void updateHardware();
|
||||
void updateRemote();
|
||||
void updateStatus();
|
||||
void openDeviceSettingsDialog(const QPoint& p);
|
||||
};
|
||||
|
@ -236,7 +236,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="decimationLabel">
|
||||
<property name="text">
|
||||
<string>Dec</string>
|
||||
<string>Rem ch Dec</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -288,25 +288,6 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="channelRateText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Effective channel rate (kS/s)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0000k</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="filterChainText">
|
||||
<property name="minimumSize">
|
||||
@ -365,7 +346,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="positionLabel">
|
||||
<property name="text">
|
||||
<string>Pos</string>
|
||||
<string>Rem ch Pos</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "remoteinputudphandler.h"
|
||||
#include "remoteinput.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(RemoteInputUDPHandler::MsgReportSampleRateChange, Message)
|
||||
MESSAGE_CLASS_DEFINITION(RemoteInputUDPHandler::MsgReportMetaDataChange, Message)
|
||||
MESSAGE_CLASS_DEFINITION(RemoteInputUDPHandler::MsgUDPAddressAndPort, Message)
|
||||
|
||||
RemoteInputUDPHandler::RemoteInputUDPHandler(SampleSinkFifo *sampleFifo, DeviceAPI *deviceAPI) :
|
||||
@ -55,7 +55,7 @@ RemoteInputUDPHandler::RemoteInputUDPHandler(SampleSinkFifo *sampleFifo, DeviceA
|
||||
m_throttlems(REMOTEINPUT_THROTTLE_MS),
|
||||
m_readLengthSamples(0),
|
||||
m_readLength(0),
|
||||
m_converterBuffer(0),
|
||||
m_converterBuffer(nullptr),
|
||||
m_converterBufferNbSamples(0),
|
||||
m_throttleToggle(false),
|
||||
m_autoCorrBuffer(true)
|
||||
@ -149,7 +149,7 @@ void RemoteInputUDPHandler::stop()
|
||||
if (m_dataSocket)
|
||||
{
|
||||
delete m_dataSocket;
|
||||
m_dataSocket = 0;
|
||||
m_dataSocket = nullptr;
|
||||
}
|
||||
|
||||
m_centerFrequency = 0;
|
||||
@ -213,6 +213,18 @@ void RemoteInputUDPHandler::processData()
|
||||
{
|
||||
m_remoteInputBuffer.writeData(m_udpBuf);
|
||||
const RemoteMetaDataFEC& metaData = m_remoteInputBuffer.getCurrentMeta();
|
||||
|
||||
if (!(m_currentMeta == metaData))
|
||||
{
|
||||
m_currentMeta = metaData;
|
||||
|
||||
if (m_messageQueueToInput)
|
||||
{
|
||||
MsgReportMetaDataChange *msg = MsgReportMetaDataChange::create(m_currentMeta);
|
||||
m_messageQueueToInput->push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
bool change = false;
|
||||
|
||||
m_tv_msec = m_remoteInputBuffer.getTVOutMSec();
|
||||
@ -227,13 +239,6 @@ void RemoteInputUDPHandler::processData()
|
||||
{
|
||||
disconnectTimer();
|
||||
adjustNbDecoderSlots(metaData);
|
||||
|
||||
if (m_messageQueueToInput)
|
||||
{
|
||||
MsgReportSampleRateChange *msg = MsgReportSampleRateChange::create(metaData.m_sampleRate);
|
||||
m_messageQueueToInput->push(msg);
|
||||
}
|
||||
|
||||
m_samplerate = metaData.m_sampleRate;
|
||||
change = true;
|
||||
}
|
||||
@ -256,6 +261,8 @@ void RemoteInputUDPHandler::processData()
|
||||
}
|
||||
|
||||
m_dataSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, getDataSocketBufferSize());
|
||||
m_elapsedTimer.restart();
|
||||
m_throttlems = 0;
|
||||
connectTimer();
|
||||
}
|
||||
}
|
||||
@ -310,7 +317,7 @@ void RemoteInputUDPHandler::tick()
|
||||
if (throttlems != m_throttlems)
|
||||
{
|
||||
m_throttlems = throttlems;
|
||||
m_readLengthSamples = (m_remoteInputBuffer.getCurrentMeta().m_sampleRate * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000;
|
||||
m_readLengthSamples = (m_currentMeta.m_sampleRate * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000;
|
||||
m_throttleToggle = !m_throttleToggle;
|
||||
}
|
||||
|
||||
@ -319,27 +326,19 @@ void RemoteInputUDPHandler::tick()
|
||||
m_readLengthSamples += m_remoteInputBuffer.getRWBalanceCorrection();
|
||||
// Eliminate negative or excessively high values
|
||||
m_readLengthSamples = m_readLengthSamples < 0 ?
|
||||
0 : m_readLengthSamples > (int) m_remoteInputBuffer.getCurrentMeta().m_sampleRate/5 ?
|
||||
0 : m_readLengthSamples > (int) m_currentMeta.m_sampleRate/5 ?
|
||||
m_remoteInputBuffer.getCurrentMeta().m_sampleRate/5 : m_readLengthSamples;
|
||||
}
|
||||
|
||||
const RemoteMetaDataFEC& metaData = m_remoteInputBuffer.getCurrentMeta();
|
||||
m_readLength = m_readLengthSamples * (m_currentMeta.m_sampleBytes & 0xF) * 2;
|
||||
|
||||
if (!(m_currentMeta == metaData))
|
||||
{
|
||||
m_currentMeta = metaData;
|
||||
emit metaChanged();
|
||||
}
|
||||
|
||||
m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2;
|
||||
|
||||
if (metaData.m_sampleBits == SDR_RX_SAMP_SZ) // no conversion
|
||||
if (m_currentMeta.m_sampleBits == SDR_RX_SAMP_SZ) // no conversion
|
||||
{
|
||||
// read samples directly feeding the SampleFifo (no callback)
|
||||
m_sampleFifo->write(reinterpret_cast<quint8*>(m_remoteInputBuffer.readData(m_readLength)), m_readLength);
|
||||
m_samplesCount += m_readLengthSamples;
|
||||
}
|
||||
else if ((metaData.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 16)) // 8 -> 16
|
||||
else if ((m_currentMeta.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 16)) // 8 -> 16
|
||||
{
|
||||
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
|
||||
{
|
||||
@ -356,7 +355,7 @@ void RemoteInputUDPHandler::tick()
|
||||
m_converterBuffer[is] += buf[2*is] * (1<<8); // I -> LSB
|
||||
}
|
||||
}
|
||||
else if ((metaData.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 24)) // 8 -> 24
|
||||
else if ((m_currentMeta.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 24)) // 8 -> 24
|
||||
{
|
||||
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
|
||||
{
|
||||
@ -374,7 +373,7 @@ void RemoteInputUDPHandler::tick()
|
||||
|
||||
m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
|
||||
}
|
||||
else if (metaData.m_sampleBits == 16) // 16 -> 24
|
||||
else if (m_currentMeta.m_sampleBits == 16) // 16 -> 24
|
||||
{
|
||||
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
|
||||
{
|
||||
@ -392,7 +391,7 @@ void RemoteInputUDPHandler::tick()
|
||||
|
||||
m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
|
||||
}
|
||||
else if (metaData.m_sampleBits == 24) // 24 -> 16
|
||||
else if (m_currentMeta.m_sampleBits == 24) // 24 -> 16
|
||||
{
|
||||
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
|
||||
{
|
||||
@ -413,7 +412,7 @@ void RemoteInputUDPHandler::tick()
|
||||
}
|
||||
else // invalid size
|
||||
{
|
||||
qWarning("RemoteInputUDPHandler::tick: unexpected sample size in stream: %d bits", (int) metaData.m_sampleBits);
|
||||
qWarning("RemoteInputUDPHandler::tick: unexpected sample size in stream: %d bits", (int) m_currentMeta.m_sampleBits);
|
||||
}
|
||||
|
||||
if (m_tickCount < m_rateDivider)
|
||||
|
@ -38,23 +38,23 @@ class RemoteInputUDPHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
class MsgReportSampleRateChange : public Message {
|
||||
class MsgReportMetaDataChange : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getSampleRate() const { return m_sampleRate; }
|
||||
const RemoteMetaDataFEC& getMetaData() const { return m_metaData; }
|
||||
|
||||
static MsgReportSampleRateChange* create(int sampleRate)
|
||||
static MsgReportMetaDataChange* create(const RemoteMetaDataFEC& metaData)
|
||||
{
|
||||
return new MsgReportSampleRateChange(sampleRate);
|
||||
return new MsgReportMetaDataChange(metaData);
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_sampleRate;
|
||||
RemoteMetaDataFEC m_metaData;
|
||||
|
||||
MsgReportSampleRateChange(int sampleRate) :
|
||||
MsgReportMetaDataChange(const RemoteMetaDataFEC& metaData) :
|
||||
Message(),
|
||||
m_sampleRate(sampleRate)
|
||||
m_metaData(metaData)
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -79,9 +79,6 @@ public:
|
||||
public slots:
|
||||
void dataReadyRead();
|
||||
|
||||
signals:
|
||||
void metaChanged();
|
||||
|
||||
private:
|
||||
class MsgUDPAddressAndPort : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
Loading…
Reference in New Issue
Block a user