mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-04 05:30:32 -05:00 
			
		
		
		
	M17 modulator: SMS packet +
This commit is contained in:
		
							parent
							
								
									dd2233f763
								
							
						
					
					
						commit
						f10da64717
					
				@ -39,6 +39,7 @@ public:
 | 
				
			|||||||
    using codec_frame_t = std::array<uint8_t, 16>;
 | 
					    using codec_frame_t = std::array<uint8_t, 16>;
 | 
				
			||||||
    using payload_t = std::array<uint8_t, 34>;      // Bytes in the payload of a data frame.
 | 
					    using payload_t = std::array<uint8_t, 34>;      // Bytes in the payload of a data frame.
 | 
				
			||||||
    using frame_t = std::array<uint8_t, 46>;        // M17 frame (without sync word).
 | 
					    using frame_t = std::array<uint8_t, 46>;        // M17 frame (without sync word).
 | 
				
			||||||
 | 
					    using packet_t = std::array<uint8_t, 25>;       // Packet payload
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static constexpr std::array<uint8_t, 2> SYNC_WORD = {0x32, 0x43};
 | 
					    static constexpr std::array<uint8_t, 2> SYNC_WORD = {0x32, 0x43};
 | 
				
			||||||
    static constexpr std::array<uint8_t, 2> LSF_SYNC_WORD = {0x55, 0xF7};
 | 
					    static constexpr std::array<uint8_t, 2> LSF_SYNC_WORD = {0x55, 0xF7};
 | 
				
			||||||
@ -57,6 +58,31 @@ public:
 | 
				
			|||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template <typename T, size_t N>
 | 
				
			||||||
 | 
					    static std::array<int8_t, N * 4> bytes_to_symbols(const std::array<T, N>& bytes)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::array<int8_t, N * 4> result;
 | 
				
			||||||
 | 
					        size_t index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (auto b : bytes)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            for (size_t i = 0; i != 4; ++i)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                result[index++] = bits_to_symbol(b >> 6);
 | 
				
			||||||
 | 
					                b <<= 2;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static
 | 
				
			||||||
 | 
					    void make_preamble(std::array<uint8_t, 48>& preamble_bytes)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Preamble is simple... bytes -> symbols.
 | 
				
			||||||
 | 
					        preamble_bytes.fill(0x77);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Encode each LSF segment into a Golay-encoded LICH segment bitstream.
 | 
					     * Encode each LSF segment into a Golay-encoded LICH segment bitstream.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -109,7 +135,7 @@ public:
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Construct the link setup frame and split into LICH segments.
 | 
					     * Construct the link setup frame and split into LICH segments.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void make_link_setup(lich_t& lich, mobilinkd::M17Modulator::frame_t lsf)
 | 
					    void make_link_setup(lich_t& lich, mobilinkd::M17Modulator::frame_t lsf_frame)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        using namespace mobilinkd;
 | 
					        using namespace mobilinkd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -141,12 +167,14 @@ public:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto encoded = conv_encode(lsf);
 | 
					        auto encoded = conv_encode(lsf);
 | 
				
			||||||
 | 
					        auto size = puncture_bytes(encoded, lsf_frame, P1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto size = puncture_bytes(encoded, lsf, P1);
 | 
					        if (size != 368) {
 | 
				
			||||||
        assert(size == 368);
 | 
					            std::cerr << "make_link_setup: incorrect size (not 368)" << size;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        interleaver_.interleave(lsf);
 | 
					        interleaver_.interleave(lsf_frame);
 | 
				
			||||||
        randomizer_(lsf);
 | 
					        randomizer_(lsf_frame);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -168,7 +196,7 @@ public:
 | 
				
			|||||||
     * Assemble the audio frame payload by appending the frame number, encoded audio,
 | 
					     * Assemble the audio frame payload by appending the frame number, encoded audio,
 | 
				
			||||||
     * and CRC, then convolutionally coding and puncturing the data.
 | 
					     * and CRC, then convolutionally coding and puncturing the data.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    payload_t make_payload(uint16_t frame_number, const codec_frame_t& payload)
 | 
					    payload_t make_audio_payload(uint16_t frame_number, const codec_frame_t& payload)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::array<uint8_t, 20> data;   // FN, Audio, CRC = 2 + 16 + 2;
 | 
					        std::array<uint8_t, 20> data;   // FN, Audio, CRC = 2 + 16 + 2;
 | 
				
			||||||
        data[0] = uint8_t((frame_number >> 8) & 0xFF);
 | 
					        data[0] = uint8_t((frame_number >> 8) & 0xFF);
 | 
				
			||||||
@ -188,7 +216,47 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        payload_t punctured;
 | 
					        payload_t punctured;
 | 
				
			||||||
        auto size = puncture_bytes(encoded, punctured, mobilinkd::P2);
 | 
					        auto size = puncture_bytes(encoded, punctured, mobilinkd::P2);
 | 
				
			||||||
        assert(size == 272);
 | 
					
 | 
				
			||||||
 | 
					        if (size != 272) {
 | 
				
			||||||
 | 
					            std::cerr << "mobilinkd::M17Modulator::make_audio_payload: incorrect size (not 272)" << size;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return punctured;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    frame_t make_packet_frame(uint8_t packet_number, bool last_packet, packet_t packet, int packet_size)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::array<uint8_t, 26> packet_assembly;
 | 
				
			||||||
 | 
					        packet_assembly.fill(0);
 | 
				
			||||||
 | 
					        std::copy(packet.begin(), packet.begin() + packet_size, packet_assembly.begin());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (packet_number == 0) {
 | 
				
			||||||
 | 
					            crc_.reset();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < packet_size; i++) {
 | 
				
			||||||
 | 
					            crc_(packet[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (last_packet)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            packet_assembly[25] = 0x80 | (packet_size<<2);
 | 
				
			||||||
 | 
					            packet_assembly[packet_size]   = crc_.get_bytes()[1];
 | 
				
			||||||
 | 
					            packet_assembly[packet_size+1] = crc_.get_bytes()[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            packet_assembly[25] = (packet_number<<2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::array<uint8_t, 2*26+1> encoded = conv_encode(packet_assembly);
 | 
				
			||||||
 | 
					        frame_t punctured;
 | 
				
			||||||
 | 
					        auto size = puncture_bytes(encoded, punctured, mobilinkd::P3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (size != 368) {
 | 
				
			||||||
 | 
					            std::cerr << "mobilinkd::M17Modulator::make_packet_frame: incorrect size (not 368)" << size;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return punctured;
 | 
					        return punctured;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -280,24 +348,6 @@ private:
 | 
				
			|||||||
        return encoded_call;
 | 
					        return encoded_call;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template <typename T, size_t N>
 | 
					 | 
				
			||||||
    static std::array<int8_t, N * 4> bytes_to_symbols(const std::array<T, N>& bytes)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::array<int8_t, N * 4> result;
 | 
					 | 
				
			||||||
        size_t index = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (auto b : bytes)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            for (size_t i = 0; i != 4; ++i)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                result[index++] = bits_to_symbol(b >> 6);
 | 
					 | 
				
			||||||
                b <<= 2;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return result;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    template <typename T, size_t N>
 | 
					    template <typename T, size_t N>
 | 
				
			||||||
    static std::array<T, N * 2 + 1> conv_encode(std::array<T, N> data)
 | 
					    static std::array<T, N * 2 + 1> conv_encode(std::array<T, N> data)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ set(modm17_SOURCES
 | 
				
			|||||||
    m17mod.cpp
 | 
					    m17mod.cpp
 | 
				
			||||||
    m17modbaseband.cpp
 | 
					    m17modbaseband.cpp
 | 
				
			||||||
    m17modsource.cpp
 | 
					    m17modsource.cpp
 | 
				
			||||||
 | 
					    m17modprocessor.cpp
 | 
				
			||||||
	m17modplugin.cpp
 | 
						m17modplugin.cpp
 | 
				
			||||||
    m17modsettings.cpp
 | 
					    m17modsettings.cpp
 | 
				
			||||||
    m17modwebapiadapter.cpp
 | 
					    m17modwebapiadapter.cpp
 | 
				
			||||||
@ -13,6 +14,7 @@ set(modm17_HEADERS
 | 
				
			|||||||
	m17mod.h
 | 
						m17mod.h
 | 
				
			||||||
    m17modbaseband.h
 | 
					    m17modbaseband.h
 | 
				
			||||||
    m17modsource.h
 | 
					    m17modsource.h
 | 
				
			||||||
 | 
					    m17modprocessor.h
 | 
				
			||||||
	m17modplugin.h
 | 
						m17modplugin.h
 | 
				
			||||||
    m17modsettings.h
 | 
					    m17modsettings.h
 | 
				
			||||||
    m17modwebapiadapter.h
 | 
					    m17modwebapiadapter.h
 | 
				
			||||||
@ -20,6 +22,8 @@ set(modm17_HEADERS
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
include_directories(
 | 
					include_directories(
 | 
				
			||||||
    ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
 | 
					    ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
 | 
				
			||||||
 | 
					    ${CODEC2_INCLUDE_DIR}
 | 
				
			||||||
 | 
					    ${CMAKE_SOURCE_DIR}/modems
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(NOT SERVER_MODE)
 | 
					if(NOT SERVER_MODE)
 | 
				
			||||||
@ -48,12 +52,18 @@ add_library(${TARGET_NAME} SHARED
 | 
				
			|||||||
	${modm17_SOURCES}
 | 
						${modm17_SOURCES}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(CODEC2_EXTERNAL)
 | 
				
			||||||
 | 
					    add_dependencies(${TARGET_NAME} codec2)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(${TARGET_NAME}
 | 
					target_link_libraries(${TARGET_NAME}
 | 
				
			||||||
    Qt5::Core
 | 
					    Qt5::Core
 | 
				
			||||||
    ${TARGET_LIB}
 | 
					    ${TARGET_LIB}
 | 
				
			||||||
	sdrbase
 | 
						sdrbase
 | 
				
			||||||
	${TARGET_LIB_GUI}
 | 
						${TARGET_LIB_GUI}
 | 
				
			||||||
    swagger
 | 
					    swagger
 | 
				
			||||||
 | 
					    ${CODEC2_LIBRARIES}
 | 
				
			||||||
 | 
					    modems
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
 | 
					install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
 | 
				
			||||||
 | 
				
			|||||||
@ -294,7 +294,9 @@ void M17Mod::applySettings(const M17ModSettings& settings, bool force)
 | 
				
			|||||||
            << " m_toneFrequency: " << settings.m_toneFrequency
 | 
					            << " m_toneFrequency: " << settings.m_toneFrequency
 | 
				
			||||||
            << " m_channelMute: " << settings.m_channelMute
 | 
					            << " m_channelMute: " << settings.m_channelMute
 | 
				
			||||||
            << " m_playLoop: " << settings.m_playLoop
 | 
					            << " m_playLoop: " << settings.m_playLoop
 | 
				
			||||||
            << " m_modAFInput " << settings.m_modAFInput
 | 
					            << " m_m17Mode " << settings.m_m17Mode
 | 
				
			||||||
 | 
					            << " m_audioType " << settings.m_audioType
 | 
				
			||||||
 | 
					            << " m_packetType " << settings.m_packetType
 | 
				
			||||||
            << " m_audioDeviceName: " << settings.m_audioDeviceName
 | 
					            << " m_audioDeviceName: " << settings.m_audioDeviceName
 | 
				
			||||||
            << " m_useReverseAPI: " << settings.m_useReverseAPI
 | 
					            << " m_useReverseAPI: " << settings.m_useReverseAPI
 | 
				
			||||||
            << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
 | 
					            << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
 | 
				
			||||||
@ -320,8 +322,14 @@ void M17Mod::applySettings(const M17ModSettings& settings, bool force)
 | 
				
			|||||||
    if ((settings.m_playLoop != m_settings.m_playLoop) || force) {
 | 
					    if ((settings.m_playLoop != m_settings.m_playLoop) || force) {
 | 
				
			||||||
        reverseAPIKeys.append("playLoop");
 | 
					        reverseAPIKeys.append("playLoop");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if ((settings.m_modAFInput != m_settings.m_modAFInput) || force) {
 | 
					    if ((settings.m_audioType != m_settings.m_audioType) || force) {
 | 
				
			||||||
        reverseAPIKeys.append("modAFInput");
 | 
					        reverseAPIKeys.append("audioType");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((settings.m_packetType != m_settings.m_packetType) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("packetType");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((settings.m_m17Mode != m_settings.m_m17Mode) || force) {
 | 
				
			||||||
 | 
					        reverseAPIKeys.append("m17Mode");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
 | 
					    if((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
 | 
				
			||||||
        reverseAPIKeys.append("rfBandwidth");
 | 
					        reverseAPIKeys.append("rfBandwidth");
 | 
				
			||||||
@ -470,8 +478,14 @@ void M17Mod::webapiUpdateChannelSettings(
 | 
				
			|||||||
    if (channelSettingsKeys.contains("inputFrequencyOffset")) {
 | 
					    if (channelSettingsKeys.contains("inputFrequencyOffset")) {
 | 
				
			||||||
        settings.m_inputFrequencyOffset = response.getM17ModSettings()->getInputFrequencyOffset();
 | 
					        settings.m_inputFrequencyOffset = response.getM17ModSettings()->getInputFrequencyOffset();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (channelSettingsKeys.contains("modAFInput")) {
 | 
					    if (channelSettingsKeys.contains("m17Mode")) {
 | 
				
			||||||
        settings.m_modAFInput = (M17ModSettings::M17ModInputAF) response.getM17ModSettings()->getModAfInput();
 | 
					        settings.m_m17Mode = (M17ModSettings::M17Mode) response.getM17ModSettings()->getM17Mode();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioType")) {
 | 
				
			||||||
 | 
					        settings.m_audioType = (M17ModSettings::AudioType) response.getM17ModSettings()->getAudioType();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("packetType")) {
 | 
				
			||||||
 | 
					        settings.m_packetType = (M17ModSettings::PacketType) response.getM17ModSettings()->getPacketType();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (channelSettingsKeys.contains("playLoop")) {
 | 
					    if (channelSettingsKeys.contains("playLoop")) {
 | 
				
			||||||
        settings.m_playLoop = response.getM17ModSettings()->getPlayLoop() != 0;
 | 
					        settings.m_playLoop = response.getM17ModSettings()->getPlayLoop() != 0;
 | 
				
			||||||
@ -533,7 +547,9 @@ void M17Mod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
 | 
				
			|||||||
    response.getM17ModSettings()->setChannelMute(settings.m_channelMute ? 1 : 0);
 | 
					    response.getM17ModSettings()->setChannelMute(settings.m_channelMute ? 1 : 0);
 | 
				
			||||||
    response.getM17ModSettings()->setFmDeviation(settings.m_fmDeviation);
 | 
					    response.getM17ModSettings()->setFmDeviation(settings.m_fmDeviation);
 | 
				
			||||||
    response.getM17ModSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
 | 
					    response.getM17ModSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
 | 
				
			||||||
    response.getM17ModSettings()->setModAfInput((int) settings.m_modAFInput);
 | 
					    response.getM17ModSettings()->setM17Mode((int) settings.m_m17Mode);
 | 
				
			||||||
 | 
					    response.getM17ModSettings()->setAudioType((int) settings.m_audioType);
 | 
				
			||||||
 | 
					    response.getM17ModSettings()->setPacketType((int) settings.m_packetType);
 | 
				
			||||||
    response.getM17ModSettings()->setPlayLoop(settings.m_playLoop ? 1 : 0);
 | 
					    response.getM17ModSettings()->setPlayLoop(settings.m_playLoop ? 1 : 0);
 | 
				
			||||||
    response.getM17ModSettings()->setRfBandwidth(settings.m_rfBandwidth);
 | 
					    response.getM17ModSettings()->setRfBandwidth(settings.m_rfBandwidth);
 | 
				
			||||||
    response.getM17ModSettings()->setRgbColor(settings.m_rgbColor);
 | 
					    response.getM17ModSettings()->setRgbColor(settings.m_rgbColor);
 | 
				
			||||||
@ -673,8 +689,14 @@ void M17Mod::webapiFormatChannelSettings(
 | 
				
			|||||||
    if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
 | 
					    if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
 | 
				
			||||||
        swgM17ModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
 | 
					        swgM17ModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (channelSettingsKeys.contains("modAFInput") || force) {
 | 
					    if (channelSettingsKeys.contains("m17Mode") || force) {
 | 
				
			||||||
        swgM17ModSettings->setModAfInput((int) settings.m_modAFInput);
 | 
					        swgM17ModSettings->setM17Mode((int) settings.m_m17Mode);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("audioType") || force) {
 | 
				
			||||||
 | 
					        swgM17ModSettings->setAudioType((int) settings.m_audioType);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (channelSettingsKeys.contains("packetType") || force) {
 | 
				
			||||||
 | 
					        swgM17ModSettings->setPacketType((int) settings.m_packetType);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (channelSettingsKeys.contains("audioDeviceName") || force) {
 | 
					    if (channelSettingsKeys.contains("audioDeviceName") || force) {
 | 
				
			||||||
        swgM17ModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName));
 | 
					        swgM17ModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName));
 | 
				
			||||||
@ -764,3 +786,8 @@ int M17Mod::getFeedbackAudioSampleRate() const
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    return m_basebandSource->getFeedbackAudioSampleRate();
 | 
					    return m_basebandSource->getFeedbackAudioSampleRate();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17Mod::sendPacket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_basebandSource->sendPacket();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -233,6 +233,7 @@ public:
 | 
				
			|||||||
    uint32_t getNumberOfDeviceStreams() const;
 | 
					    uint32_t getNumberOfDeviceStreams() const;
 | 
				
			||||||
    int getAudioSampleRate() const;
 | 
					    int getAudioSampleRate() const;
 | 
				
			||||||
    int getFeedbackAudioSampleRate() const;
 | 
					    int getFeedbackAudioSampleRate() const;
 | 
				
			||||||
 | 
					    void sendPacket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static const char* const m_channelIdURI;
 | 
					    static const char* const m_channelIdURI;
 | 
				
			||||||
    static const char* const m_channelId;
 | 
					    static const char* const m_channelId;
 | 
				
			||||||
 | 
				
			|||||||
@ -196,12 +196,12 @@ void M17ModBaseband::applySettings(const M17ModSettings& settings, bool force)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((settings.m_modAFInput != m_settings.m_modAFInput) || force)
 | 
					    if ((settings.m_audioType != m_settings.m_audioType) || force)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
 | 
					        AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
 | 
				
			||||||
        int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
 | 
					        int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (settings.m_modAFInput == M17ModSettings::M17ModInputAudio) {
 | 
					        if (settings.m_audioType == M17ModSettings::AudioInput) {
 | 
				
			||||||
            audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
 | 
					            audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            audioDeviceManager->removeAudioSource(getAudioFifo());
 | 
					            audioDeviceManager->removeAudioSource(getAudioFifo());
 | 
				
			||||||
 | 
				
			|||||||
@ -70,6 +70,7 @@ public:
 | 
				
			|||||||
    AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
 | 
					    AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
 | 
				
			||||||
    AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); }
 | 
					    AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); }
 | 
				
			||||||
    void setChannel(ChannelAPI *channel);
 | 
					    void setChannel(ChannelAPI *channel);
 | 
				
			||||||
 | 
					    void sendPacket() { m_source.sendPacket(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 | 
				
			|||||||
@ -182,6 +182,22 @@ void M17ModGUI::on_toneFrequency_valueChanged(int value)
 | 
				
			|||||||
    applySettings();
 | 
					    applySettings();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_fmAudio_toggled(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_fmAudioMode = checked;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((checked) && (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeM17Audio))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_settings.m_m17Mode = M17ModSettings::M17Mode::M17ModeFMAudio;
 | 
				
			||||||
 | 
					        applySettings();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if ((!checked) && (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeFMAudio))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_settings.m_m17Mode = M17ModSettings::M17Mode::M17ModeM17Audio;
 | 
				
			||||||
 | 
					        applySettings();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModGUI::on_channelMute_toggled(bool checked)
 | 
					void M17ModGUI::on_channelMute_toggled(bool checked)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    m_settings.m_channelMute = checked;
 | 
					    m_settings.m_channelMute = checked;
 | 
				
			||||||
@ -196,9 +212,13 @@ void M17ModGUI::on_playLoop_toggled(bool checked)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void M17ModGUI::on_play_toggled(bool checked)
 | 
					void M17ModGUI::on_play_toggled(bool checked)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ui->tone->setEnabled(!checked); // release other source inputs
 | 
					    m_settings.m_audioType = checked ? M17ModSettings::AudioFile : M17ModSettings::AudioNone;
 | 
				
			||||||
    ui->mic->setEnabled(!checked);
 | 
					    m_settings.m_m17Mode = checked ?
 | 
				
			||||||
    m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputFile : M17ModSettings::M17ModInputNone;
 | 
					        m_fmAudioMode ?
 | 
				
			||||||
 | 
					            M17ModSettings::M17Mode::M17ModeFMAudio
 | 
				
			||||||
 | 
					            : M17ModSettings::M17Mode::M17ModeM17Audio
 | 
				
			||||||
 | 
					        : M17ModSettings::M17ModeNone;
 | 
				
			||||||
 | 
					    displayModes();
 | 
				
			||||||
    applySettings();
 | 
					    applySettings();
 | 
				
			||||||
    ui->navTimeSlider->setEnabled(!checked);
 | 
					    ui->navTimeSlider->setEnabled(!checked);
 | 
				
			||||||
    m_enableNavTime = !checked;
 | 
					    m_enableNavTime = !checked;
 | 
				
			||||||
@ -206,17 +226,20 @@ void M17ModGUI::on_play_toggled(bool checked)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void M17ModGUI::on_tone_toggled(bool checked)
 | 
					void M17ModGUI::on_tone_toggled(bool checked)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ui->play->setEnabled(!checked); // release other source inputs
 | 
					    m_settings.m_m17Mode = checked ? M17ModSettings::M17ModeFMTone : M17ModSettings::M17ModeNone;
 | 
				
			||||||
    ui->mic->setEnabled(!checked);
 | 
					    displayModes();
 | 
				
			||||||
    m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputTone : M17ModSettings::M17ModInputNone;
 | 
					 | 
				
			||||||
    applySettings();
 | 
					    applySettings();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModGUI::on_mic_toggled(bool checked)
 | 
					void M17ModGUI::on_mic_toggled(bool checked)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ui->play->setEnabled(!checked); // release other source inputs
 | 
					    m_settings.m_audioType = checked ? M17ModSettings::AudioInput : M17ModSettings::AudioNone;
 | 
				
			||||||
    ui->tone->setEnabled(!checked); // release other source inputs
 | 
					    m_settings.m_m17Mode = checked ?
 | 
				
			||||||
    m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputAudio : M17ModSettings::M17ModInputNone;
 | 
					        m_fmAudioMode ?
 | 
				
			||||||
 | 
					            M17ModSettings::M17Mode::M17ModeFMAudio
 | 
				
			||||||
 | 
					            : M17ModSettings::M17Mode::M17ModeM17Audio
 | 
				
			||||||
 | 
					        : M17ModSettings::M17ModeNone;
 | 
				
			||||||
 | 
					    displayModes();
 | 
				
			||||||
    applySettings();
 | 
					    applySettings();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -261,6 +284,66 @@ void M17ModGUI::on_showFileDialog_clicked(bool checked)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_packetMode_toggled(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_m17Mode = checked ? M17ModSettings::M17ModeM17Packet : M17ModSettings::M17ModeNone;
 | 
				
			||||||
 | 
					    displayModes();
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_sendPacket_clicked(bool)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_m17Mod->sendPacket();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_loopPacket_toggled(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) checked;
 | 
				
			||||||
 | 
					    // TODO
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_loopPacketInterval_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void) value;
 | 
				
			||||||
 | 
					    // TODO
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_packetDataWidget_currentChanged(int index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_packetType = indexToPacketType(index);
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_source_editingFinished()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_sourceCall = ui->source->text();
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_destination_editingFinished()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_destCall = ui->destination->text();
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_insertPosition_toggled(bool checked)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_insertPosition = checked;
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_can_valueChanged(int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_can = value;
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::on_smsText_editingFinished()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_settings.m_smsText = ui->smsText->toPlainText();
 | 
				
			||||||
 | 
					    applySettings();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModGUI::configureFileName()
 | 
					void M17ModGUI::configureFileName()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qDebug() << "M17ModGUI::configureFileName: " << m_fileName.toStdString().c_str();
 | 
					    qDebug() << "M17ModGUI::configureFileName: " << m_fileName.toStdString().c_str();
 | 
				
			||||||
@ -333,6 +416,7 @@ M17ModGUI::M17ModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
 | 
				
			|||||||
    m_deviceCenterFrequency(0),
 | 
					    m_deviceCenterFrequency(0),
 | 
				
			||||||
    m_basebandSampleRate(1),
 | 
					    m_basebandSampleRate(1),
 | 
				
			||||||
	m_doApplySettings(true),
 | 
						m_doApplySettings(true),
 | 
				
			||||||
 | 
					    m_fmAudioMode(false),
 | 
				
			||||||
    m_recordLength(0),
 | 
					    m_recordLength(0),
 | 
				
			||||||
    m_recordSampleRate(48000),
 | 
					    m_recordSampleRate(48000),
 | 
				
			||||||
    m_samplesCount(0),
 | 
					    m_samplesCount(0),
 | 
				
			||||||
@ -447,23 +531,101 @@ void M17ModGUI::displaySettings()
 | 
				
			|||||||
    ui->channelMute->setChecked(m_settings.m_channelMute);
 | 
					    ui->channelMute->setChecked(m_settings.m_channelMute);
 | 
				
			||||||
    ui->playLoop->setChecked(m_settings.m_playLoop);
 | 
					    ui->playLoop->setChecked(m_settings.m_playLoop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ui->tone->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputTone) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone));
 | 
					    displayModes();
 | 
				
			||||||
    ui->mic->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputAudio) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone));
 | 
					    ui->fmAudio->setChecked(m_fmAudioMode);
 | 
				
			||||||
    ui->play->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputFile) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone));
 | 
					    ui->packetDataWidget->setCurrentIndex(packetTypeToIndex(m_settings.m_packetType));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    ui->tone->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputTone);
 | 
					 | 
				
			||||||
    ui->mic->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputAudio);
 | 
					 | 
				
			||||||
    ui->play->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputFile);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable);
 | 
					    ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable);
 | 
				
			||||||
    ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0));
 | 
					    ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0));
 | 
				
			||||||
    ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2));
 | 
					    ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->source->setText(m_settings.m_sourceCall);
 | 
				
			||||||
 | 
					    ui->destination->setText(m_settings.m_destCall);
 | 
				
			||||||
 | 
					    ui->insertPosition->setChecked(m_settings.m_insertPosition);
 | 
				
			||||||
 | 
					    ui->can->setValue(m_settings.m_can);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->smsText->setText(m_settings.m_smsText);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui->aprsFromText->setText(m_settings.m_aprsCallsign);
 | 
				
			||||||
 | 
					    ui->aprsData->setText(m_settings.m_aprsData);
 | 
				
			||||||
 | 
					    ui->aprsTo->lineEdit()->setText(m_settings.m_aprsTo);
 | 
				
			||||||
 | 
					    ui->aprsVia->lineEdit()->setText(m_settings.m_aprsVia);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getRollupContents()->restoreState(m_rollupState);
 | 
					    getRollupContents()->restoreState(m_rollupState);
 | 
				
			||||||
    updateAbsoluteCenterFrequency();
 | 
					    updateAbsoluteCenterFrequency();
 | 
				
			||||||
    blockApplySettings(false);
 | 
					    blockApplySettings(false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModGUI::displayModes()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    qDebug("M17ModGUI::displayModes: m_m17Mode: %d m_audioType: %d",
 | 
				
			||||||
 | 
					        (int) m_settings.m_m17Mode, (int) m_settings.m_audioType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeM17Packet)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->packetMode->setChecked(true);
 | 
				
			||||||
 | 
					        ui->packetMode->setEnabled(true);
 | 
				
			||||||
 | 
					        ui->tone->setChecked(false);
 | 
				
			||||||
 | 
					        ui->mic->setChecked(false);
 | 
				
			||||||
 | 
					        ui->play->setChecked(false);
 | 
				
			||||||
 | 
					        ui->tone->setEnabled(false);
 | 
				
			||||||
 | 
					        ui->mic->setEnabled(false);
 | 
				
			||||||
 | 
					        ui->play->setEnabled(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeFMTone)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->tone->setChecked(true);
 | 
				
			||||||
 | 
					        ui->tone->setEnabled(true);
 | 
				
			||||||
 | 
					        ui->packetMode->setChecked(false);
 | 
				
			||||||
 | 
					        ui->mic->setChecked(false);
 | 
				
			||||||
 | 
					        ui->play->setChecked(false);
 | 
				
			||||||
 | 
					        ui->packetMode->setEnabled(false);
 | 
				
			||||||
 | 
					        ui->mic->setEnabled(false);
 | 
				
			||||||
 | 
					        ui->play->setEnabled(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if ((m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeFMAudio) ||
 | 
				
			||||||
 | 
					        (m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeM17Audio))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->tone->setChecked(false);
 | 
				
			||||||
 | 
					        ui->packetMode->setChecked(false);
 | 
				
			||||||
 | 
					        ui->tone->setEnabled(false);
 | 
				
			||||||
 | 
					        ui->packetMode->setEnabled(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_settings.m_audioType == M17ModSettings::AudioType::AudioInput)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ui->mic->setChecked(true);
 | 
				
			||||||
 | 
					            ui->mic->setEnabled(true);
 | 
				
			||||||
 | 
					            ui->play->setChecked(false);
 | 
				
			||||||
 | 
					            ui->play->setEnabled(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (m_settings.m_audioType == M17ModSettings::AudioType::AudioFile)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ui->play->setChecked(true);
 | 
				
			||||||
 | 
					            ui->play->setEnabled(true);
 | 
				
			||||||
 | 
					            ui->mic->setChecked(false);
 | 
				
			||||||
 | 
					            ui->mic->setEnabled(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (m_settings.m_audioType == M17ModSettings::AudioType::AudioNone)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ui->mic->setChecked(false);
 | 
				
			||||||
 | 
					            ui->play->setChecked(false);
 | 
				
			||||||
 | 
					            ui->mic->setEnabled(true);
 | 
				
			||||||
 | 
					            ui->play->setEnabled(true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeNone)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ui->packetMode->setChecked(false);
 | 
				
			||||||
 | 
					        ui->tone->setChecked(false);
 | 
				
			||||||
 | 
					        ui->mic->setChecked(false);
 | 
				
			||||||
 | 
					        ui->play->setChecked(false);
 | 
				
			||||||
 | 
					        ui->packetMode->setEnabled(true);
 | 
				
			||||||
 | 
					        ui->tone->setEnabled(true);
 | 
				
			||||||
 | 
					        ui->mic->setEnabled(true);
 | 
				
			||||||
 | 
					        ui->play->setEnabled(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModGUI::leaveEvent(QEvent* event)
 | 
					void M17ModGUI::leaveEvent(QEvent* event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	m_channelMarker.setHighlighted(false);
 | 
						m_channelMarker.setHighlighted(false);
 | 
				
			||||||
@ -534,7 +696,7 @@ void M17ModGUI::tick()
 | 
				
			|||||||
        m_feedbackAudioSampleRate = feedbackAudioSampleRate;
 | 
					        m_feedbackAudioSampleRate = feedbackAudioSampleRate;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == M17ModSettings::M17ModInputFile))
 | 
					    if (((++m_tickCount & 0xf) == 0) && (m_settings.m_audioType == M17ModSettings::AudioFile))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        M17Mod::MsgConfigureFileSourceStreamTiming* message = M17Mod::MsgConfigureFileSourceStreamTiming::create();
 | 
					        M17Mod::MsgConfigureFileSourceStreamTiming* message = M17Mod::MsgConfigureFileSourceStreamTiming::create();
 | 
				
			||||||
        m_m17Mod->getInputMessageQueue()->push(message);
 | 
					        m_m17Mod->getInputMessageQueue()->push(message);
 | 
				
			||||||
@ -591,9 +753,41 @@ void M17ModGUI::makeUIConnections()
 | 
				
			|||||||
    QObject::connect(ui->showFileDialog, &QPushButton::clicked, this, &M17ModGUI::on_showFileDialog_clicked);
 | 
					    QObject::connect(ui->showFileDialog, &QPushButton::clicked, this, &M17ModGUI::on_showFileDialog_clicked);
 | 
				
			||||||
    QObject::connect(ui->feedbackEnable, &QToolButton::toggled, this, &M17ModGUI::on_feedbackEnable_toggled);
 | 
					    QObject::connect(ui->feedbackEnable, &QToolButton::toggled, this, &M17ModGUI::on_feedbackEnable_toggled);
 | 
				
			||||||
    QObject::connect(ui->feedbackVolume, &QDial::valueChanged, this, &M17ModGUI::on_feedbackVolume_valueChanged);
 | 
					    QObject::connect(ui->feedbackVolume, &QDial::valueChanged, this, &M17ModGUI::on_feedbackVolume_valueChanged);
 | 
				
			||||||
 | 
					    QObject::connect(ui->fmAudio, &ButtonSwitch::toggled, this, &M17ModGUI::on_fmAudio_toggled);
 | 
				
			||||||
 | 
					    QObject::connect(ui->packetMode, &ButtonSwitch::toggled, this, &M17ModGUI::on_packetMode_toggled);
 | 
				
			||||||
 | 
					    QObject::connect(ui->sendPacket, &QPushButton::clicked, this, &M17ModGUI::on_sendPacket_clicked);
 | 
				
			||||||
 | 
					    QObject::connect(ui->loopPacket, &ButtonSwitch::toggled, this, &M17ModGUI::on_loopPacket_toggled);
 | 
				
			||||||
 | 
					    QObject::connect(ui->loopPacketInterval, &QDial::valueChanged, this, &M17ModGUI::on_loopPacketInterval_valueChanged);
 | 
				
			||||||
 | 
					    QObject::connect(ui->smsText, &CustomTextEdit::editingFinished, this, &M17ModGUI::on_smsText_editingFinished);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModGUI::updateAbsoluteCenterFrequency()
 | 
					void M17ModGUI::updateAbsoluteCenterFrequency()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
 | 
					    setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					M17ModSettings::PacketType M17ModGUI::indexToPacketType(int index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch(index)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case 0:
 | 
				
			||||||
 | 
					            return M17ModSettings::PacketType::PacketSMS;
 | 
				
			||||||
 | 
					        case 1:
 | 
				
			||||||
 | 
					            return M17ModSettings::PacketType::PacketAPRS;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return M17ModSettings::PacketType::PacketNone;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int M17ModGUI::packetTypeToIndex(M17ModSettings::PacketType type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch(type)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case M17ModSettings::PacketType::PacketSMS:
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        case M17ModSettings::PacketType::PacketAPRS:
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -76,6 +76,7 @@ private:
 | 
				
			|||||||
    qint64 m_deviceCenterFrequency;
 | 
					    qint64 m_deviceCenterFrequency;
 | 
				
			||||||
    int m_basebandSampleRate;
 | 
					    int m_basebandSampleRate;
 | 
				
			||||||
    bool m_doApplySettings;
 | 
					    bool m_doApplySettings;
 | 
				
			||||||
 | 
					    bool m_fmAudioMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    M17Mod* m_m17Mod;
 | 
					    M17Mod* m_m17Mod;
 | 
				
			||||||
    MovingAverageUtil<double, double, 20> m_channelPowerDbAvg;
 | 
					    MovingAverageUtil<double, double, 20> m_channelPowerDbAvg;
 | 
				
			||||||
@ -88,7 +89,6 @@ private:
 | 
				
			|||||||
    int m_feedbackAudioSampleRate;
 | 
					    int m_feedbackAudioSampleRate;
 | 
				
			||||||
    std::size_t m_tickCount;
 | 
					    std::size_t m_tickCount;
 | 
				
			||||||
    bool m_enableNavTime;
 | 
					    bool m_enableNavTime;
 | 
				
			||||||
    M17ModSettings::M17ModInputAF m_modAFInput;
 | 
					 | 
				
			||||||
    MessageQueue m_inputMessageQueue;
 | 
					    MessageQueue m_inputMessageQueue;
 | 
				
			||||||
    QRegExpValidator m_dcsCodeValidator;
 | 
					    QRegExpValidator m_dcsCodeValidator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -98,11 +98,14 @@ private:
 | 
				
			|||||||
    void blockApplySettings(bool block);
 | 
					    void blockApplySettings(bool block);
 | 
				
			||||||
    void applySettings(bool force = false);
 | 
					    void applySettings(bool force = false);
 | 
				
			||||||
    void displaySettings();
 | 
					    void displaySettings();
 | 
				
			||||||
 | 
					    void displayModes();
 | 
				
			||||||
    void updateWithStreamData();
 | 
					    void updateWithStreamData();
 | 
				
			||||||
    void updateWithStreamTime();
 | 
					    void updateWithStreamTime();
 | 
				
			||||||
    bool handleMessage(const Message& message);
 | 
					    bool handleMessage(const Message& message);
 | 
				
			||||||
    void makeUIConnections();
 | 
					    void makeUIConnections();
 | 
				
			||||||
    void updateAbsoluteCenterFrequency();
 | 
					    void updateAbsoluteCenterFrequency();
 | 
				
			||||||
 | 
					    M17ModSettings::PacketType indexToPacketType(int index);
 | 
				
			||||||
 | 
					    int packetTypeToIndex(M17ModSettings::PacketType type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void leaveEvent(QEvent*);
 | 
					    void leaveEvent(QEvent*);
 | 
				
			||||||
    void enterEvent(QEvent*);
 | 
					    void enterEvent(QEvent*);
 | 
				
			||||||
@ -115,6 +118,7 @@ private slots:
 | 
				
			|||||||
    void on_rfBW_valueChanged(int value);
 | 
					    void on_rfBW_valueChanged(int value);
 | 
				
			||||||
    void on_fmDev_valueChanged(int value);
 | 
					    void on_fmDev_valueChanged(int value);
 | 
				
			||||||
    void on_toneFrequency_valueChanged(int value);
 | 
					    void on_toneFrequency_valueChanged(int value);
 | 
				
			||||||
 | 
					    void on_fmAudio_toggled(bool checked);
 | 
				
			||||||
    void on_volume_valueChanged(int value);
 | 
					    void on_volume_valueChanged(int value);
 | 
				
			||||||
    void on_channelMute_toggled(bool checked);
 | 
					    void on_channelMute_toggled(bool checked);
 | 
				
			||||||
    void on_tone_toggled(bool checked);
 | 
					    void on_tone_toggled(bool checked);
 | 
				
			||||||
@ -128,6 +132,17 @@ private slots:
 | 
				
			|||||||
    void on_feedbackEnable_toggled(bool checked);
 | 
					    void on_feedbackEnable_toggled(bool checked);
 | 
				
			||||||
    void on_feedbackVolume_valueChanged(int value);
 | 
					    void on_feedbackVolume_valueChanged(int value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void on_packetMode_toggled(bool checked);
 | 
				
			||||||
 | 
					    void on_sendPacket_clicked(bool checked);
 | 
				
			||||||
 | 
					    void on_loopPacket_toggled(bool checked);
 | 
				
			||||||
 | 
					    void on_loopPacketInterval_valueChanged(int value);
 | 
				
			||||||
 | 
					    void on_packetDataWidget_currentChanged(int index);
 | 
				
			||||||
 | 
					    void on_source_editingFinished();
 | 
				
			||||||
 | 
					    void on_destination_editingFinished();
 | 
				
			||||||
 | 
					    void on_insertPosition_toggled(bool checked);
 | 
				
			||||||
 | 
					    void on_can_valueChanged(int value);
 | 
				
			||||||
 | 
					    void on_smsText_editingFinished();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void onWidgetRolled(QWidget* widget, bool rollDown);
 | 
					    void onWidgetRolled(QWidget* widget, bool rollDown);
 | 
				
			||||||
    void onMenuDialogCalled(const QPoint& p);
 | 
					    void onMenuDialogCalled(const QPoint& p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
    <x>0</x>
 | 
					    <x>0</x>
 | 
				
			||||||
    <y>0</y>
 | 
					    <y>0</y>
 | 
				
			||||||
    <width>360</width>
 | 
					    <width>360</width>
 | 
				
			||||||
    <height>278</height>
 | 
					    <height>568</height>
 | 
				
			||||||
   </rect>
 | 
					   </rect>
 | 
				
			||||||
  </property>
 | 
					  </property>
 | 
				
			||||||
  <property name="sizePolicy">
 | 
					  <property name="sizePolicy">
 | 
				
			||||||
@ -40,13 +40,13 @@
 | 
				
			|||||||
  <property name="windowTitle">
 | 
					  <property name="windowTitle">
 | 
				
			||||||
   <string>M17 Modulator</string>
 | 
					   <string>M17 Modulator</string>
 | 
				
			||||||
  </property>
 | 
					  </property>
 | 
				
			||||||
  <widget class="QWidget" name="settingsContainer" native="true">
 | 
					  <widget class="QWidget" name="aSettingsContainer" native="true">
 | 
				
			||||||
   <property name="geometry">
 | 
					   <property name="geometry">
 | 
				
			||||||
    <rect>
 | 
					    <rect>
 | 
				
			||||||
     <x>0</x>
 | 
					     <x>0</x>
 | 
				
			||||||
     <y>0</y>
 | 
					     <y>0</y>
 | 
				
			||||||
     <width>358</width>
 | 
					     <width>358</width>
 | 
				
			||||||
     <height>271</height>
 | 
					     <height>105</height>
 | 
				
			||||||
    </rect>
 | 
					    </rect>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
   <property name="minimumSize">
 | 
					   <property name="minimumSize">
 | 
				
			||||||
@ -286,13 +286,6 @@
 | 
				
			|||||||
      </item>
 | 
					      </item>
 | 
				
			||||||
     </layout>
 | 
					     </layout>
 | 
				
			||||||
    </item>
 | 
					    </item>
 | 
				
			||||||
    <item>
 | 
					 | 
				
			||||||
     <widget class="Line" name="line_5">
 | 
					 | 
				
			||||||
      <property name="orientation">
 | 
					 | 
				
			||||||
       <enum>Qt::Horizontal</enum>
 | 
					 | 
				
			||||||
      </property>
 | 
					 | 
				
			||||||
     </widget>
 | 
					 | 
				
			||||||
    </item>
 | 
					 | 
				
			||||||
    <item>
 | 
					    <item>
 | 
				
			||||||
     <layout class="QHBoxLayout" name="volumeLayout">
 | 
					     <layout class="QHBoxLayout" name="volumeLayout">
 | 
				
			||||||
      <item>
 | 
					      <item>
 | 
				
			||||||
@ -364,12 +357,42 @@
 | 
				
			|||||||
      </item>
 | 
					      </item>
 | 
				
			||||||
     </layout>
 | 
					     </layout>
 | 
				
			||||||
    </item>
 | 
					    </item>
 | 
				
			||||||
 | 
					   </layout>
 | 
				
			||||||
 | 
					  </widget>
 | 
				
			||||||
 | 
					  <widget class="QWidget" name="bAudioContainer" native="true">
 | 
				
			||||||
 | 
					   <property name="geometry">
 | 
				
			||||||
 | 
					    <rect>
 | 
				
			||||||
 | 
					     <x>0</x>
 | 
				
			||||||
 | 
					     <y>107</y>
 | 
				
			||||||
 | 
					     <width>361</width>
 | 
				
			||||||
 | 
					     <height>140</height>
 | 
				
			||||||
 | 
					    </rect>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <property name="windowTitle">
 | 
				
			||||||
 | 
					    <string>Audio</string>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <layout class="QVBoxLayout" name="verticalLayout_2">
 | 
				
			||||||
 | 
					    <property name="spacing">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="leftMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="topMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="rightMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="bottomMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
    <item>
 | 
					    <item>
 | 
				
			||||||
     <layout class="QHBoxLayout" name="recordFileSelectLayout">
 | 
					     <layout class="QHBoxLayout" name="recordFileSelectLayout">
 | 
				
			||||||
      <item>
 | 
					      <item>
 | 
				
			||||||
       <widget class="ButtonSwitch" name="tone">
 | 
					       <widget class="ButtonSwitch" name="tone">
 | 
				
			||||||
        <property name="toolTip">
 | 
					        <property name="toolTip">
 | 
				
			||||||
         <string>FM tone modulation</string>
 | 
					         <string>Analog FM tone modulation</string>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="text">
 | 
					        <property name="text">
 | 
				
			||||||
         <string>...</string>
 | 
					         <string>...</string>
 | 
				
			||||||
@ -424,6 +447,22 @@
 | 
				
			|||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
       </widget>
 | 
					       </widget>
 | 
				
			||||||
      </item>
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="ButtonSwitch" name="fmAudio">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>35</width>
 | 
				
			||||||
 | 
					          <height>16777215</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Modulate audio as analog FM (for testing)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>FM</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
      <item>
 | 
					      <item>
 | 
				
			||||||
       <widget class="ButtonSwitch" name="mic">
 | 
					       <widget class="ButtonSwitch" name="mic">
 | 
				
			||||||
        <property name="toolTip">
 | 
					        <property name="toolTip">
 | 
				
			||||||
@ -532,13 +571,6 @@
 | 
				
			|||||||
      </item>
 | 
					      </item>
 | 
				
			||||||
     </layout>
 | 
					     </layout>
 | 
				
			||||||
    </item>
 | 
					    </item>
 | 
				
			||||||
    <item>
 | 
					 | 
				
			||||||
     <widget class="Line" name="line_4">
 | 
					 | 
				
			||||||
      <property name="orientation">
 | 
					 | 
				
			||||||
       <enum>Qt::Horizontal</enum>
 | 
					 | 
				
			||||||
      </property>
 | 
					 | 
				
			||||||
     </widget>
 | 
					 | 
				
			||||||
    </item>
 | 
					 | 
				
			||||||
    <item>
 | 
					    <item>
 | 
				
			||||||
     <layout class="QHBoxLayout" name="fileNameLayout">
 | 
					     <layout class="QHBoxLayout" name="fileNameLayout">
 | 
				
			||||||
      <item>
 | 
					      <item>
 | 
				
			||||||
@ -704,6 +736,606 @@
 | 
				
			|||||||
    </item>
 | 
					    </item>
 | 
				
			||||||
   </layout>
 | 
					   </layout>
 | 
				
			||||||
  </widget>
 | 
					  </widget>
 | 
				
			||||||
 | 
					  <widget class="QWidget" name="cPacketContainer" native="true">
 | 
				
			||||||
 | 
					   <property name="geometry">
 | 
				
			||||||
 | 
					    <rect>
 | 
				
			||||||
 | 
					     <x>0</x>
 | 
				
			||||||
 | 
					     <y>247</y>
 | 
				
			||||||
 | 
					     <width>358</width>
 | 
				
			||||||
 | 
					     <height>193</height>
 | 
				
			||||||
 | 
					    </rect>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <property name="windowTitle">
 | 
				
			||||||
 | 
					    <string>Packet</string>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
				
			||||||
 | 
					    <property name="spacing">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="leftMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="topMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="rightMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="bottomMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="horizontalLayout">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="ButtonSwitch" name="packetMode">
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Packet mode</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>PKT</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QPushButton" name="sendPacket">
 | 
				
			||||||
 | 
					        <property name="sizePolicy">
 | 
				
			||||||
 | 
					         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
 | 
				
			||||||
 | 
					          <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					          <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					         </sizepolicy>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Send packet</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string/>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="icon">
 | 
				
			||||||
 | 
					         <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					          <normaloff>:/stream.png</normaloff>:/stream.png</iconset>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="ButtonSwitch" name="loopPacket">
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Send packets in a loop</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string/>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="icon">
 | 
				
			||||||
 | 
					         <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					          <normaloff>:/playloop.png</normaloff>:/playloop.png</iconset>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QDial" name="loopPacketInterval">
 | 
				
			||||||
 | 
					        <property name="maximumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>24</width>
 | 
				
			||||||
 | 
					          <height>24</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Interval between packets (s)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimum">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="maximum">
 | 
				
			||||||
 | 
					         <number>600</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="pageStep">
 | 
				
			||||||
 | 
					         <number>1</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="value">
 | 
				
			||||||
 | 
					         <number>60</number>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="loopPacketIntervalText">
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>Interval between packets (s)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>600</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <spacer name="horizontalSpacer_4">
 | 
				
			||||||
 | 
					        <property name="orientation">
 | 
				
			||||||
 | 
					         <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="sizeHint" stdset="0">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>40</width>
 | 
				
			||||||
 | 
					          <height>20</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </spacer>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <widget class="QTabWidget" name="packetDataWidget">
 | 
				
			||||||
 | 
					      <property name="toolTip">
 | 
				
			||||||
 | 
					       <string>Packet data</string>
 | 
				
			||||||
 | 
					      </property>
 | 
				
			||||||
 | 
					      <property name="tabPosition">
 | 
				
			||||||
 | 
					       <enum>QTabWidget::East</enum>
 | 
				
			||||||
 | 
					      </property>
 | 
				
			||||||
 | 
					      <property name="currentIndex">
 | 
				
			||||||
 | 
					       <number>0</number>
 | 
				
			||||||
 | 
					      </property>
 | 
				
			||||||
 | 
					      <widget class="QWidget" name="pktSMS">
 | 
				
			||||||
 | 
					       <property name="toolTip">
 | 
				
			||||||
 | 
					        <string>SMS data</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <attribute name="icon">
 | 
				
			||||||
 | 
					        <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					         <normaloff>:/sms.png</normaloff>:/sms.png</iconset>
 | 
				
			||||||
 | 
					       </attribute>
 | 
				
			||||||
 | 
					       <attribute name="title">
 | 
				
			||||||
 | 
					        <string/>
 | 
				
			||||||
 | 
					       </attribute>
 | 
				
			||||||
 | 
					       <attribute name="toolTip">
 | 
				
			||||||
 | 
					        <string>SMS</string>
 | 
				
			||||||
 | 
					       </attribute>
 | 
				
			||||||
 | 
					       <widget class="CustomTextEdit" name="smsText">
 | 
				
			||||||
 | 
					        <property name="geometry">
 | 
				
			||||||
 | 
					         <rect>
 | 
				
			||||||
 | 
					          <x>0</x>
 | 
				
			||||||
 | 
					          <y>10</y>
 | 
				
			||||||
 | 
					          <width>307</width>
 | 
				
			||||||
 | 
					          <height>120</height>
 | 
				
			||||||
 | 
					         </rect>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="toolTip">
 | 
				
			||||||
 | 
					         <string>SMS text</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					      <widget class="QWidget" name="pktAPRS">
 | 
				
			||||||
 | 
					       <property name="toolTip">
 | 
				
			||||||
 | 
					        <string>APRS data</string>
 | 
				
			||||||
 | 
					       </property>
 | 
				
			||||||
 | 
					       <attribute name="icon">
 | 
				
			||||||
 | 
					        <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
				
			||||||
 | 
					         <normaloff>:/world.png</normaloff>:/world.png</iconset>
 | 
				
			||||||
 | 
					       </attribute>
 | 
				
			||||||
 | 
					       <attribute name="title">
 | 
				
			||||||
 | 
					        <string/>
 | 
				
			||||||
 | 
					       </attribute>
 | 
				
			||||||
 | 
					       <attribute name="toolTip">
 | 
				
			||||||
 | 
					        <string>APRS</string>
 | 
				
			||||||
 | 
					       </attribute>
 | 
				
			||||||
 | 
					       <widget class="QWidget" name="horizontalLayoutWidget">
 | 
				
			||||||
 | 
					        <property name="geometry">
 | 
				
			||||||
 | 
					         <rect>
 | 
				
			||||||
 | 
					          <x>0</x>
 | 
				
			||||||
 | 
					          <y>40</y>
 | 
				
			||||||
 | 
					          <width>301</width>
 | 
				
			||||||
 | 
					          <height>34</height>
 | 
				
			||||||
 | 
					         </rect>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <layout class="QHBoxLayout" name="toLayout">
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QLabel" name="aprsToLabel">
 | 
				
			||||||
 | 
					           <property name="sizePolicy">
 | 
				
			||||||
 | 
					            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
 | 
				
			||||||
 | 
					             <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					             <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					            </sizepolicy>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="text">
 | 
				
			||||||
 | 
					            <string>To</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QComboBox" name="aprsTo">
 | 
				
			||||||
 | 
					           <property name="sizePolicy">
 | 
				
			||||||
 | 
					            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
 | 
				
			||||||
 | 
					             <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					             <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					            </sizepolicy>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="minimumSize">
 | 
				
			||||||
 | 
					            <size>
 | 
				
			||||||
 | 
					             <width>100</width>
 | 
				
			||||||
 | 
					             <height>0</height>
 | 
				
			||||||
 | 
					            </size>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="toolTip">
 | 
				
			||||||
 | 
					            <string>Enter destination</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="editable">
 | 
				
			||||||
 | 
					            <bool>true</bool>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="currentText">
 | 
				
			||||||
 | 
					            <string>APRS</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="currentIndex">
 | 
				
			||||||
 | 
					            <number>0</number>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <item>
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>APRS</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </item>
 | 
				
			||||||
 | 
					           <item>
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>APZ</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </item>
 | 
				
			||||||
 | 
					           <item>
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>CQ</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </item>
 | 
				
			||||||
 | 
					           <item>
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>BEACON</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </item>
 | 
				
			||||||
 | 
					           <item>
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>CALLSIGN-SSID</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </item>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QLabel" name="aprsViaLabel">
 | 
				
			||||||
 | 
					           <property name="sizePolicy">
 | 
				
			||||||
 | 
					            <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
 | 
				
			||||||
 | 
					             <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					             <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					            </sizepolicy>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="text">
 | 
				
			||||||
 | 
					            <string>Via</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QComboBox" name="aprsVia">
 | 
				
			||||||
 | 
					           <property name="sizePolicy">
 | 
				
			||||||
 | 
					            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
 | 
				
			||||||
 | 
					             <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					             <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					            </sizepolicy>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="toolTip">
 | 
				
			||||||
 | 
					            <string>Enter routing</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="editable">
 | 
				
			||||||
 | 
					            <bool>true</bool>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <item>
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>WIDE2-2</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </item>
 | 
				
			||||||
 | 
					           <item>
 | 
				
			||||||
 | 
					            <property name="text">
 | 
				
			||||||
 | 
					             <string>ARISS</string>
 | 
				
			||||||
 | 
					            </property>
 | 
				
			||||||
 | 
					           </item>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <spacer name="horizontalSpacer_5">
 | 
				
			||||||
 | 
					           <property name="orientation">
 | 
				
			||||||
 | 
					            <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="sizeHint" stdset="0">
 | 
				
			||||||
 | 
					            <size>
 | 
				
			||||||
 | 
					             <width>40</width>
 | 
				
			||||||
 | 
					             <height>20</height>
 | 
				
			||||||
 | 
					            </size>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </spacer>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					        </layout>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					       <widget class="QWidget" name="horizontalLayoutWidget_2">
 | 
				
			||||||
 | 
					        <property name="geometry">
 | 
				
			||||||
 | 
					         <rect>
 | 
				
			||||||
 | 
					          <x>0</x>
 | 
				
			||||||
 | 
					          <y>80</y>
 | 
				
			||||||
 | 
					          <width>301</width>
 | 
				
			||||||
 | 
					          <height>34</height>
 | 
				
			||||||
 | 
					         </rect>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <layout class="QHBoxLayout" name="aprsDataLayout">
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QLabel" name="aprsDataLabel">
 | 
				
			||||||
 | 
					           <property name="layoutDirection">
 | 
				
			||||||
 | 
					            <enum>Qt::LeftToRight</enum>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="text">
 | 
				
			||||||
 | 
					            <string>Data</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QLineEdit" name="aprsData">
 | 
				
			||||||
 | 
					           <property name="toolTip">
 | 
				
			||||||
 | 
					            <string>Enter data to transmit.
 | 
				
			||||||
 | 
					            </string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="text">
 | 
				
			||||||
 | 
					            <string>>Using SDRangel</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="maxLength">
 | 
				
			||||||
 | 
					            <number>256</number>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					        </layout>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					       <widget class="QWidget" name="horizontalLayoutWidget_3">
 | 
				
			||||||
 | 
					        <property name="geometry">
 | 
				
			||||||
 | 
					         <rect>
 | 
				
			||||||
 | 
					          <x>0</x>
 | 
				
			||||||
 | 
					          <y>0</y>
 | 
				
			||||||
 | 
					          <width>301</width>
 | 
				
			||||||
 | 
					          <height>34</height>
 | 
				
			||||||
 | 
					         </rect>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <layout class="QHBoxLayout" name="fromLayout">
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QLabel" name="label_2">
 | 
				
			||||||
 | 
					           <property name="text">
 | 
				
			||||||
 | 
					            <string>From</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="QLineEdit" name="aprsFromText">
 | 
				
			||||||
 | 
					           <property name="toolTip">
 | 
				
			||||||
 | 
					            <string>Enter your amateur radio callsign and optionally a SSID. E.g. M7RCE or M7RCE-1</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="text">
 | 
				
			||||||
 | 
					            <string>MYCALL</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="maxLength">
 | 
				
			||||||
 | 
					            <number>10</number>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <widget class="ButtonSwitch" name="aprsInsertPosition">
 | 
				
			||||||
 | 
					           <property name="toolTip">
 | 
				
			||||||
 | 
					            <string>Insert position (latitude and longitude)</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="text">
 | 
				
			||||||
 | 
					            <string>...</string>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="icon">
 | 
				
			||||||
 | 
					            <iconset>
 | 
				
			||||||
 | 
					             <normalon>:/gps.png</normalon>
 | 
				
			||||||
 | 
					            </iconset>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </widget>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <spacer name="aprsFromLabel">
 | 
				
			||||||
 | 
					           <property name="orientation">
 | 
				
			||||||
 | 
					            <enum>Qt::Horizontal</enum>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					           <property name="sizeHint" stdset="0">
 | 
				
			||||||
 | 
					            <size>
 | 
				
			||||||
 | 
					             <width>40</width>
 | 
				
			||||||
 | 
					             <height>20</height>
 | 
				
			||||||
 | 
					            </size>
 | 
				
			||||||
 | 
					           </property>
 | 
				
			||||||
 | 
					          </spacer>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					        </layout>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </widget>
 | 
				
			||||||
 | 
					     </widget>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					   </layout>
 | 
				
			||||||
 | 
					  </widget>
 | 
				
			||||||
 | 
					  <widget class="QWidget" name="dDigitalContainer" native="true">
 | 
				
			||||||
 | 
					   <property name="geometry">
 | 
				
			||||||
 | 
					    <rect>
 | 
				
			||||||
 | 
					     <x>0</x>
 | 
				
			||||||
 | 
					     <y>442</y>
 | 
				
			||||||
 | 
					     <width>358</width>
 | 
				
			||||||
 | 
					     <height>120</height>
 | 
				
			||||||
 | 
					    </rect>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <property name="windowTitle">
 | 
				
			||||||
 | 
					    <string>Digital</string>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
 | 
					   <layout class="QVBoxLayout" name="verticalLayout_4" stretch="0">
 | 
				
			||||||
 | 
					    <property name="spacing">
 | 
				
			||||||
 | 
					     <number>3</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="leftMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="topMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="rightMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <property name="bottomMargin">
 | 
				
			||||||
 | 
					     <number>2</number>
 | 
				
			||||||
 | 
					    </property>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QHBoxLayout" name="horizontalLayout_2">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="TVScreen" name="screenTV" native="true">
 | 
				
			||||||
 | 
					        <property name="sizePolicy">
 | 
				
			||||||
 | 
					         <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
 | 
				
			||||||
 | 
					          <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					          <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					         </sizepolicy>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="minimumSize">
 | 
				
			||||||
 | 
					         <size>
 | 
				
			||||||
 | 
					          <width>100</width>
 | 
				
			||||||
 | 
					          <height>100</height>
 | 
				
			||||||
 | 
					         </size>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QFrame" name="frame">
 | 
				
			||||||
 | 
					        <property name="frameShape">
 | 
				
			||||||
 | 
					         <enum>QFrame::StyledPanel</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="frameShadow">
 | 
				
			||||||
 | 
					         <enum>QFrame::Raised</enum>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <widget class="QComboBox" name="baudRate">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>10</x>
 | 
				
			||||||
 | 
					           <y>10</y>
 | 
				
			||||||
 | 
					           <width>60</width>
 | 
				
			||||||
 | 
					           <height>24</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="sizePolicy">
 | 
				
			||||||
 | 
					          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
 | 
				
			||||||
 | 
					           <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					           <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					          </sizepolicy>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="minimumSize">
 | 
				
			||||||
 | 
					          <size>
 | 
				
			||||||
 | 
					           <width>35</width>
 | 
				
			||||||
 | 
					           <height>0</height>
 | 
				
			||||||
 | 
					          </size>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="maximumSize">
 | 
				
			||||||
 | 
					          <size>
 | 
				
			||||||
 | 
					           <width>16777215</width>
 | 
				
			||||||
 | 
					           <height>16777215</height>
 | 
				
			||||||
 | 
					          </size>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="toolTip">
 | 
				
			||||||
 | 
					          <string>Baud rate: 2.4k: NXDN48, dPMR 4.8k: DMR, D-Star, YSF, NXDN96</string>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <item>
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string>4.8k</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </item>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					        <widget class="QLabel" name="sourceLabel">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>10</x>
 | 
				
			||||||
 | 
					           <y>40</y>
 | 
				
			||||||
 | 
					           <width>21</width>
 | 
				
			||||||
 | 
					           <height>28</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="text">
 | 
				
			||||||
 | 
					          <string>Src</string>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					        <widget class="QLineEdit" name="source">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>40</x>
 | 
				
			||||||
 | 
					           <y>40</y>
 | 
				
			||||||
 | 
					           <width>100</width>
 | 
				
			||||||
 | 
					           <height>24</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					        <widget class="QLabel" name="destinationLabel">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>10</x>
 | 
				
			||||||
 | 
					           <y>70</y>
 | 
				
			||||||
 | 
					           <width>21</width>
 | 
				
			||||||
 | 
					           <height>28</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="text">
 | 
				
			||||||
 | 
					          <string>Dst</string>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					        <widget class="QLineEdit" name="destination">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>40</x>
 | 
				
			||||||
 | 
					           <y>70</y>
 | 
				
			||||||
 | 
					           <width>100</width>
 | 
				
			||||||
 | 
					           <height>24</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					        <widget class="ButtonSwitch" name="insertPosition">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>150</x>
 | 
				
			||||||
 | 
					           <y>40</y>
 | 
				
			||||||
 | 
					           <width>24</width>
 | 
				
			||||||
 | 
					           <height>24</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="toolTip">
 | 
				
			||||||
 | 
					          <string>Insert position (latitude and longitude)</string>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="text">
 | 
				
			||||||
 | 
					          <string>...</string>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="icon">
 | 
				
			||||||
 | 
					          <iconset>
 | 
				
			||||||
 | 
					           <normalon>:/gps.png</normalon>
 | 
				
			||||||
 | 
					          </iconset>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					        <widget class="QLabel" name="destinationLabel_2">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>150</x>
 | 
				
			||||||
 | 
					           <y>70</y>
 | 
				
			||||||
 | 
					           <width>30</width>
 | 
				
			||||||
 | 
					           <height>28</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="text">
 | 
				
			||||||
 | 
					          <string>CAN</string>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					        <widget class="QSpinBox" name="can">
 | 
				
			||||||
 | 
					         <property name="geometry">
 | 
				
			||||||
 | 
					          <rect>
 | 
				
			||||||
 | 
					           <x>180</x>
 | 
				
			||||||
 | 
					           <y>70</y>
 | 
				
			||||||
 | 
					           <width>56</width>
 | 
				
			||||||
 | 
					           <height>28</height>
 | 
				
			||||||
 | 
					          </rect>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="maximum">
 | 
				
			||||||
 | 
					          <number>255</number>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					         <property name="value">
 | 
				
			||||||
 | 
					          <number>10</number>
 | 
				
			||||||
 | 
					         </property>
 | 
				
			||||||
 | 
					        </widget>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					   </layout>
 | 
				
			||||||
 | 
					  </widget>
 | 
				
			||||||
 </widget>
 | 
					 </widget>
 | 
				
			||||||
 <customwidgets>
 | 
					 <customwidgets>
 | 
				
			||||||
  <customwidget>
 | 
					  <customwidget>
 | 
				
			||||||
@ -723,12 +1355,23 @@
 | 
				
			|||||||
   <extends>QToolButton</extends>
 | 
					   <extends>QToolButton</extends>
 | 
				
			||||||
   <header>gui/buttonswitch.h</header>
 | 
					   <header>gui/buttonswitch.h</header>
 | 
				
			||||||
  </customwidget>
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>TVScreen</class>
 | 
				
			||||||
 | 
					   <extends>QWidget</extends>
 | 
				
			||||||
 | 
					   <header>gui/tvscreen.h</header>
 | 
				
			||||||
 | 
					   <container>1</container>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
  <customwidget>
 | 
					  <customwidget>
 | 
				
			||||||
   <class>LevelMeterVU</class>
 | 
					   <class>LevelMeterVU</class>
 | 
				
			||||||
   <extends>QWidget</extends>
 | 
					   <extends>QWidget</extends>
 | 
				
			||||||
   <header>gui/levelmeter.h</header>
 | 
					   <header>gui/levelmeter.h</header>
 | 
				
			||||||
   <container>1</container>
 | 
					   <container>1</container>
 | 
				
			||||||
  </customwidget>
 | 
					  </customwidget>
 | 
				
			||||||
 | 
					  <customwidget>
 | 
				
			||||||
 | 
					   <class>CustomTextEdit</class>
 | 
				
			||||||
 | 
					   <extends>QTextEdit</extends>
 | 
				
			||||||
 | 
					   <header>gui/customtextedit.h</header>
 | 
				
			||||||
 | 
					  </customwidget>
 | 
				
			||||||
 </customwidgets>
 | 
					 </customwidgets>
 | 
				
			||||||
 <resources>
 | 
					 <resources>
 | 
				
			||||||
  <include location="../../../sdrgui/resources/res.qrc"/>
 | 
					  <include location="../../../sdrgui/resources/res.qrc"/>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										99
									
								
								plugins/channeltx/modm17/m17modprocessor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								plugins/channeltx/modm17/m17modprocessor.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Copyright (C) 2022 Edouard Griffiths, F4EXB                                   //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// This program is free software; you can redistribute it and/or modify          //
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by          //
 | 
				
			||||||
 | 
					// the Free Software Foundation as version 3 of the License, or                  //
 | 
				
			||||||
 | 
					// (at your option) any later version.                                           //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// This program 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 General Public License V3 for more details.                               //
 | 
				
			||||||
 | 
					//                                                                               //
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License             //
 | 
				
			||||||
 | 
					// along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "m17/M17Modulator.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "m17modprocessor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					M17ModProcessor::M17ModProcessor()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_basebandFifo.setSampleSize(sizeof(int16_t), 48000);
 | 
				
			||||||
 | 
					    connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					M17ModProcessor::~M17ModProcessor()
 | 
				
			||||||
 | 
					{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool M17ModProcessor::handleMessage(const Message& cmd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (MsgSendSMS::match(cmd))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const MsgSendSMS& notif = (const MsgSendSMS&) cmd;
 | 
				
			||||||
 | 
					        QByteArray packetBytes = notif.getSMSText().toUtf8();
 | 
				
			||||||
 | 
					        packetBytes.prepend(0x05); // SMS standard type
 | 
				
			||||||
 | 
					        packetBytes.truncate(798); // Maximum packet size is 798 payload + 2 bytes CRC = 800 bytes (32*25)
 | 
				
			||||||
 | 
					        processPacket(notif.getSourceCall(), notif.getDestCall(), packetBytes);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModProcessor::handleInputMessages()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Message* message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((message = m_inputMessageQueue.pop()) != nullptr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (handleMessage(*message)) {
 | 
				
			||||||
 | 
								delete message;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModProcessor::processPacket(const QString& sourceCall, const QString& destCall, const QByteArray& packetBytes)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    mobilinkd::M17Modulator modulator(sourceCall.toStdString(), destCall.toStdString());
 | 
				
			||||||
 | 
					    // preamble
 | 
				
			||||||
 | 
					    std::array<uint8_t, 48> preamble_bytes;
 | 
				
			||||||
 | 
					    mobilinkd::M17Modulator::make_preamble(preamble_bytes);
 | 
				
			||||||
 | 
					    std::array<int8_t, 48 * 4> fullframe_symbols = mobilinkd::M17Modulator::bytes_to_symbols(preamble_bytes);
 | 
				
			||||||
 | 
					    std::array<int16_t, 1920> baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
 | 
				
			||||||
 | 
					    m_basebandFifo.write((const quint8*) baseband.data(), 1920);
 | 
				
			||||||
 | 
					    // LSF
 | 
				
			||||||
 | 
					    mobilinkd::M17Modulator::lich_t lichSegments; // Not used for packet
 | 
				
			||||||
 | 
					    mobilinkd::M17Modulator::frame_t frame;
 | 
				
			||||||
 | 
					    modulator.make_link_setup(lichSegments, frame);
 | 
				
			||||||
 | 
					    std::array<int8_t, 46 * 4> frame_symbols = mobilinkd::M17Modulator::bytes_to_symbols(frame);
 | 
				
			||||||
 | 
					    std::copy(mobilinkd::M17Modulator::LSF_SYNC_WORD.begin(), mobilinkd::M17Modulator::LSF_SYNC_WORD.end(), fullframe_symbols.begin());
 | 
				
			||||||
 | 
					    std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2);
 | 
				
			||||||
 | 
					    baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
 | 
				
			||||||
 | 
					    m_basebandFifo.write((const quint8*) baseband.data(), 1920);
 | 
				
			||||||
 | 
					    // Packets
 | 
				
			||||||
 | 
					    std::copy(mobilinkd::M17Modulator::DATA_SYNC_WORD.begin(), mobilinkd::M17Modulator::DATA_SYNC_WORD.end(), fullframe_symbols.begin());
 | 
				
			||||||
 | 
					    mobilinkd::M17Modulator::packet_t packet;
 | 
				
			||||||
 | 
					    int remainderCount = packetBytes.size();
 | 
				
			||||||
 | 
					    int packetCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (remainderCount > 25)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::copy(packetBytes.begin() + (packetCount*25), packetBytes.begin() + ((packetCount+1)*25), packet.begin());
 | 
				
			||||||
 | 
					        frame = modulator.make_packet_frame(packetCount, false, packet, 25);
 | 
				
			||||||
 | 
					        std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2);
 | 
				
			||||||
 | 
					        baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
 | 
				
			||||||
 | 
					        m_basebandFifo.write((const quint8*) baseband.data(), 1920);
 | 
				
			||||||
 | 
					        remainderCount -= 25;
 | 
				
			||||||
 | 
					        packetCount++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::copy(packetBytes.begin() + (packetCount*25), packetBytes.begin() + (packetCount*25) + remainderCount, packet.begin());
 | 
				
			||||||
 | 
					    frame = modulator.make_packet_frame(packetCount, true, packet, remainderCount);
 | 
				
			||||||
 | 
					    std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2);
 | 
				
			||||||
 | 
					    baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols);
 | 
				
			||||||
 | 
					    m_basebandFifo.write((const quint8*) baseband.data(), 1920);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -29,22 +29,28 @@ class M17ModProcessor : public QObject
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    Q_OBJECT
 | 
					    Q_OBJECT
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    class MsgSendPacket : public Message {
 | 
					    class MsgSendSMS : public Message {
 | 
				
			||||||
        MESSAGE_CLASS_DECLARATION
 | 
					        MESSAGE_CLASS_DECLARATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        const QByteArray& getPacket() const { return m_packet; }
 | 
					        const QString& getSourceCall() const { return m_sourceCall; }
 | 
				
			||||||
 | 
					        const QString& getDestCall() const { return m_destCall; }
 | 
				
			||||||
 | 
					        const QString& getSMSText() const { return m_smsText; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static MsgSendPacket* create(const QByteArray& packet) {
 | 
					        static MsgSendSMS* create(const QString& sourceCall, const QString& destCall, const QString& smsText) {
 | 
				
			||||||
            return new MsgSendPacket(packet);
 | 
					            return new MsgSendSMS(sourceCall, destCall, smsText);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        QByteArray m_packet;
 | 
					        QString m_sourceCall;
 | 
				
			||||||
 | 
					        QString m_destCall;
 | 
				
			||||||
 | 
					        QString m_smsText;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MsgSendPacket(const QByteArray& bytes) :
 | 
					        MsgSendSMS(const QString& sourceCall, const QString& destCall, const QString& smsText) :
 | 
				
			||||||
            Message(),
 | 
					            Message(),
 | 
				
			||||||
            m_packet(bytes)
 | 
					            m_sourceCall(sourceCall),
 | 
				
			||||||
 | 
					            m_destCall(destCall),
 | 
				
			||||||
 | 
					            m_smsText(smsText)
 | 
				
			||||||
        { }
 | 
					        { }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,6 +65,7 @@ private:
 | 
				
			|||||||
    AudioFifo m_basebandFifo; //!< Samples are 16 bit integer baseband 48 kS/s samples
 | 
					    AudioFifo m_basebandFifo; //!< Samples are 16 bit integer baseband 48 kS/s samples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool handleMessage(const Message& cmd);
 | 
					    bool handleMessage(const Message& cmd);
 | 
				
			||||||
 | 
					    void processPacket(const QString& sourceCall, const QString& destCall, const QByteArray& packetBytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private slots:
 | 
					private slots:
 | 
				
			||||||
    void handleInputMessages();
 | 
					    void handleInputMessages();
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,9 @@ void M17ModSettings::resetToDefaults()
 | 
				
			|||||||
    m_playLoop = false;
 | 
					    m_playLoop = false;
 | 
				
			||||||
    m_rgbColor = QColor(255, 0, 255).rgb();
 | 
					    m_rgbColor = QColor(255, 0, 255).rgb();
 | 
				
			||||||
    m_title = "M17 Modulator";
 | 
					    m_title = "M17 Modulator";
 | 
				
			||||||
    m_modAFInput = M17ModInputAF::M17ModInputNone;
 | 
					    m_m17Mode = M17Mode::M17ModeNone;
 | 
				
			||||||
 | 
					    m_audioType = AudioType::AudioNone;
 | 
				
			||||||
 | 
					    m_packetType = PacketType::PacketNone;
 | 
				
			||||||
    m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
 | 
					    m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
 | 
				
			||||||
    m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName;
 | 
					    m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName;
 | 
				
			||||||
    m_feedbackVolumeFactor = 0.5f;
 | 
					    m_feedbackVolumeFactor = 0.5f;
 | 
				
			||||||
@ -55,6 +57,16 @@ void M17ModSettings::resetToDefaults()
 | 
				
			|||||||
    m_reverseAPIChannelIndex = 0;
 | 
					    m_reverseAPIChannelIndex = 0;
 | 
				
			||||||
    m_workspaceIndex = 0;
 | 
					    m_workspaceIndex = 0;
 | 
				
			||||||
    m_hidden = false;
 | 
					    m_hidden = false;
 | 
				
			||||||
 | 
					    m_sourceCall = "";
 | 
				
			||||||
 | 
					    m_destCall = "";
 | 
				
			||||||
 | 
					    m_insertPosition = false;
 | 
				
			||||||
 | 
					    m_can = 10;
 | 
				
			||||||
 | 
					    m_smsText = "";
 | 
				
			||||||
 | 
					    m_aprsCallsign = "MYCALL";
 | 
				
			||||||
 | 
					    m_aprsTo = "APRS";
 | 
				
			||||||
 | 
					    m_aprsVia = "WIDE2-2";
 | 
				
			||||||
 | 
					    m_aprsData = ">Using SDRangel";
 | 
				
			||||||
 | 
					    m_aprsInsertPosition = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QByteArray M17ModSettings::serialize() const
 | 
					QByteArray M17ModSettings::serialize() const
 | 
				
			||||||
@ -67,13 +79,15 @@ QByteArray M17ModSettings::serialize() const
 | 
				
			|||||||
    s.writeU32(5, m_rgbColor);
 | 
					    s.writeU32(5, m_rgbColor);
 | 
				
			||||||
    s.writeReal(6, m_toneFrequency);
 | 
					    s.writeReal(6, m_toneFrequency);
 | 
				
			||||||
    s.writeReal(7, m_volumeFactor);
 | 
					    s.writeReal(7, m_volumeFactor);
 | 
				
			||||||
 | 
					    s.writeS32(8, (int) m_m17Mode);
 | 
				
			||||||
 | 
					    s.writeS32(9, (int) m_audioType);
 | 
				
			||||||
 | 
					    s.writeS32(10, (int) m_packetType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (m_channelMarker) {
 | 
					    if (m_channelMarker) {
 | 
				
			||||||
        s.writeBlob(11, m_channelMarker->serialize());
 | 
					        s.writeBlob(11, m_channelMarker->serialize());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s.writeString(12, m_title);
 | 
					    s.writeString(12, m_title);
 | 
				
			||||||
    s.writeS32(13, (int) m_modAFInput);
 | 
					 | 
				
			||||||
    s.writeString(14, m_audioDeviceName);
 | 
					    s.writeString(14, m_audioDeviceName);
 | 
				
			||||||
    s.writeBool(15, m_useReverseAPI);
 | 
					    s.writeBool(15, m_useReverseAPI);
 | 
				
			||||||
    s.writeString(16, m_reverseAPIAddress);
 | 
					    s.writeString(16, m_reverseAPIAddress);
 | 
				
			||||||
@ -93,6 +107,19 @@ QByteArray M17ModSettings::serialize() const
 | 
				
			|||||||
    s.writeBlob(29, m_geometryBytes);
 | 
					    s.writeBlob(29, m_geometryBytes);
 | 
				
			||||||
    s.writeBool(30, m_hidden);
 | 
					    s.writeBool(30, m_hidden);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s.writeString(40, m_sourceCall);
 | 
				
			||||||
 | 
					    s.writeString(41, m_destCall);
 | 
				
			||||||
 | 
					    s.writeBool(42, m_insertPosition);
 | 
				
			||||||
 | 
					    s.writeU32(43, m_can);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s.writeString(50, m_smsText);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s.writeString(60, m_aprsCallsign);
 | 
				
			||||||
 | 
					    s.writeString(61, m_aprsTo);
 | 
				
			||||||
 | 
					    s.writeString(62, m_aprsVia);
 | 
				
			||||||
 | 
					    s.writeString(63, m_aprsData);
 | 
				
			||||||
 | 
					    s.writeBool(64, m_aprsInsertPosition);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return s.final();
 | 
					    return s.final();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -119,7 +146,13 @@ bool M17ModSettings::deserialize(const QByteArray& data)
 | 
				
			|||||||
        d.readU32(5, &m_rgbColor);
 | 
					        d.readU32(5, &m_rgbColor);
 | 
				
			||||||
        d.readReal(6, &m_toneFrequency, 1000.0);
 | 
					        d.readReal(6, &m_toneFrequency, 1000.0);
 | 
				
			||||||
        d.readReal(7, &m_volumeFactor, 1.0);
 | 
					        d.readReal(7, &m_volumeFactor, 1.0);
 | 
				
			||||||
        d.readBlob(8, &bytetmp);
 | 
					        d.readS32(8, &tmp, 0);
 | 
				
			||||||
 | 
					        m_m17Mode = tmp < 0 ? M17ModeNone : tmp > (int) M17ModeM17BERT ? M17ModeM17BERT : (M17Mode) tmp;
 | 
				
			||||||
 | 
					        d.readS32(9, &tmp, 0);
 | 
				
			||||||
 | 
					        m_audioType = tmp < 0 ? AudioNone : tmp > (int) AudioInput ? AudioInput : (AudioType) tmp;
 | 
				
			||||||
 | 
					        m_packetType = tmp < 0 ? PacketNone : tmp > (int) PacketSMS ? PacketSMS : (PacketType) tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readBlob(11, &bytetmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (m_channelMarker)
 | 
					        if (m_channelMarker)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -129,13 +162,6 @@ bool M17ModSettings::deserialize(const QByteArray& data)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        d.readString(12, &m_title, "M17 Modulator");
 | 
					        d.readString(12, &m_title, "M17 Modulator");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        d.readS32(13, &tmp, 0);
 | 
					 | 
				
			||||||
        if ((tmp < 0) || (tmp > (int) M17ModInputAF::M17ModInputTone)) {
 | 
					 | 
				
			||||||
            m_modAFInput = M17ModInputNone;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            m_modAFInput = (M17ModInputAF) tmp;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        d.readString(14, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
 | 
					        d.readString(14, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
 | 
				
			||||||
        d.readBool(15, &m_useReverseAPI, false);
 | 
					        d.readBool(15, &m_useReverseAPI, false);
 | 
				
			||||||
        d.readString(16, &m_reverseAPIAddress, "127.0.0.1");
 | 
					        d.readString(16, &m_reverseAPIAddress, "127.0.0.1");
 | 
				
			||||||
@ -167,6 +193,20 @@ bool M17ModSettings::deserialize(const QByteArray& data)
 | 
				
			|||||||
        d.readBlob(29, &m_geometryBytes);
 | 
					        d.readBlob(29, &m_geometryBytes);
 | 
				
			||||||
        d.readBool(30, &m_hidden, false);
 | 
					        d.readBool(30, &m_hidden, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readString(40, &m_sourceCall, "");
 | 
				
			||||||
 | 
					        d.readString(41, &m_destCall, "");
 | 
				
			||||||
 | 
					        d.readBool(42, &m_insertPosition, false);
 | 
				
			||||||
 | 
					        d.readU32(43, &utmp);
 | 
				
			||||||
 | 
					        m_can = utmp < 255 ? utmp : 255;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readString(50, &m_smsText, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d.readString(60, &m_aprsCallsign, "MYCALL");
 | 
				
			||||||
 | 
					        d.readString(61, &m_aprsTo, "");
 | 
				
			||||||
 | 
					        d.readString(62, &m_aprsVia, "");
 | 
				
			||||||
 | 
					        d.readString(63, &m_aprsData, "");
 | 
				
			||||||
 | 
					        d.readBool(64, &m_aprsInsertPosition, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
 | 
				
			|||||||
@ -26,12 +26,28 @@ class Serializable;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct M17ModSettings
 | 
					struct M17ModSettings
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    enum M17ModInputAF
 | 
					    enum M17Mode
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        M17ModInputNone,
 | 
					        M17ModeNone,
 | 
				
			||||||
        M17ModInputFile,
 | 
					        M17ModeFMTone,
 | 
				
			||||||
        M17ModInputAudio,
 | 
					        M17ModeFMAudio,
 | 
				
			||||||
        M17ModInputTone
 | 
					        M17ModeM17Audio,
 | 
				
			||||||
 | 
					        M17ModeM17Packet,
 | 
				
			||||||
 | 
					        M17ModeM17BERT
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum AudioType
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        AudioNone,
 | 
				
			||||||
 | 
					        AudioFile,
 | 
				
			||||||
 | 
					        AudioInput
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum PacketType
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        PacketNone,
 | 
				
			||||||
 | 
					        PacketSMS,
 | 
				
			||||||
 | 
					        PacketAPRS
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qint64 m_inputFrequencyOffset;
 | 
					    qint64 m_inputFrequencyOffset;
 | 
				
			||||||
@ -43,7 +59,9 @@ struct M17ModSettings
 | 
				
			|||||||
    bool m_playLoop;
 | 
					    bool m_playLoop;
 | 
				
			||||||
    quint32 m_rgbColor;
 | 
					    quint32 m_rgbColor;
 | 
				
			||||||
    QString m_title;
 | 
					    QString m_title;
 | 
				
			||||||
    M17ModInputAF m_modAFInput;
 | 
					    M17Mode m_m17Mode;
 | 
				
			||||||
 | 
					    AudioType m_audioType;
 | 
				
			||||||
 | 
					    PacketType m_packetType;
 | 
				
			||||||
    QString m_audioDeviceName;         //!< This is the audio device you get the audio samples from
 | 
					    QString m_audioDeviceName;         //!< This is the audio device you get the audio samples from
 | 
				
			||||||
    QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback
 | 
					    QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback
 | 
				
			||||||
    float m_feedbackVolumeFactor;
 | 
					    float m_feedbackVolumeFactor;
 | 
				
			||||||
@ -58,6 +76,19 @@ struct M17ModSettings
 | 
				
			|||||||
    QByteArray m_geometryBytes;
 | 
					    QByteArray m_geometryBytes;
 | 
				
			||||||
    bool m_hidden;
 | 
					    bool m_hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QString m_sourceCall;
 | 
				
			||||||
 | 
					    QString m_destCall;
 | 
				
			||||||
 | 
					    bool m_insertPosition;
 | 
				
			||||||
 | 
					    uint8_t m_can;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QString m_smsText;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QString m_aprsCallsign;
 | 
				
			||||||
 | 
					    QString m_aprsTo;
 | 
				
			||||||
 | 
					    QString m_aprsVia;
 | 
				
			||||||
 | 
					    QString m_aprsData;
 | 
				
			||||||
 | 
					    bool m_aprsInsertPosition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Serializable *m_channelMarker;
 | 
					    Serializable *m_channelMarker;
 | 
				
			||||||
    Serializable *m_rollupState;
 | 
					    Serializable *m_rollupState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@
 | 
				
			|||||||
#include "util/messagequeue.h"
 | 
					#include "util/messagequeue.h"
 | 
				
			||||||
#include "maincore.h"
 | 
					#include "maincore.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "m17modprocessor.h"
 | 
				
			||||||
#include "m17modsource.h"
 | 
					#include "m17modsource.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const int M17ModSource::m_levelNbSamples = 480; // every 10ms
 | 
					const int M17ModSource::m_levelNbSamples = 480; // every 10ms
 | 
				
			||||||
@ -53,12 +54,15 @@ M17ModSource::M17ModSource() :
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	m_magsq = 0.0;
 | 
						m_magsq = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_processor = new M17ModProcessor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    applySettings(m_settings, true);
 | 
					    applySettings(m_settings, true);
 | 
				
			||||||
    applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
 | 
					    applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
M17ModSource::~M17ModSource()
 | 
					M17ModSource::~M17ModSource()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    delete m_processor;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
 | 
					void M17ModSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
 | 
				
			||||||
@ -140,13 +144,22 @@ void M17ModSource::pullAudio(unsigned int nbSamplesAudio)
 | 
				
			|||||||
void M17ModSource::modulateSample()
 | 
					void M17ModSource::modulateSample()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Real t1, t;
 | 
						Real t1, t;
 | 
				
			||||||
 | 
					    bool carrier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pullAF(t);
 | 
					    if ((m_settings.m_m17Mode == M17ModSettings::M17ModeFMTone) || (m_settings.m_m17Mode == M17ModSettings::M17ModeFMAudio)) {
 | 
				
			||||||
 | 
					        pullAF(t, carrier);
 | 
				
			||||||
 | 
					    } else if (m_settings.m_m17Mode != M17ModSettings::M17ModeNone) {
 | 
				
			||||||
 | 
					        pullM17(t, carrier);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        t = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (m_settings.m_feedbackAudioEnable) {
 | 
					    if (m_settings.m_feedbackAudioEnable) {
 | 
				
			||||||
        pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f);
 | 
					        pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (carrier)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        calculateLevel(t);
 | 
					        calculateLevel(t);
 | 
				
			||||||
        t1 = m_lowpass.filter(t) * 1.2f;
 | 
					        t1 = m_lowpass.filter(t) * 1.2f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -159,6 +172,12 @@ void M17ModSource::modulateSample()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
 | 
					        m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
 | 
				
			||||||
        m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF);
 | 
					        m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        m_modSample.real(0.0f);
 | 
				
			||||||
 | 
					        m_modSample.imag(0.0f);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_demodBuffer[m_demodBufferFill] = t1 * std::numeric_limits<int16_t>::max();
 | 
					    m_demodBuffer[m_demodBufferFill] = t1 * std::numeric_limits<int16_t>::max();
 | 
				
			||||||
    ++m_demodBufferFill;
 | 
					    ++m_demodBufferFill;
 | 
				
			||||||
@ -186,14 +205,18 @@ void M17ModSource::modulateSample()
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModSource::pullAF(Real& sample)
 | 
					void M17ModSource::pullAF(Real& sample, bool& carrier)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (m_settings.m_modAFInput)
 | 
					    carrier = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m_settings.m_m17Mode == M17ModSettings::M17ModeFMTone)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    case M17ModSettings::M17ModInputTone:
 | 
					 | 
				
			||||||
        sample = m_toneNco.next();
 | 
					        sample = m_toneNco.next();
 | 
				
			||||||
        break;
 | 
					    }
 | 
				
			||||||
    case M17ModSettings::M17ModInputFile:
 | 
					    else if (m_settings.m_m17Mode == M17ModSettings::M17ModeFMAudio)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (m_settings.m_audioType == M17ModSettings::AudioFile)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
            // sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
 | 
					            // sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
 | 
				
			||||||
            // ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
 | 
					            // ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
 | 
				
			||||||
            if (m_ifstream && m_ifstream->is_open())
 | 
					            if (m_ifstream && m_ifstream->is_open())
 | 
				
			||||||
@ -221,8 +244,9 @@ void M17ModSource::pullAF(Real& sample)
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                sample = 0.0f;
 | 
					                sample = 0.0f;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        break;
 | 
					        }
 | 
				
			||||||
    case M17ModSettings::M17ModInputAudio:
 | 
					        else if (m_settings.m_audioType == M17ModSettings::AudioInput)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
            if (m_audioBufferFill < m_audioBuffer.size())
 | 
					            if (m_audioBufferFill < m_audioBuffer.size())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor;
 | 
					                sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor;
 | 
				
			||||||
@ -234,13 +258,19 @@ void M17ModSource::pullAF(Real& sample)
 | 
				
			|||||||
                qDebug("NFMModSource::pullAF: starve audio samples: size: %u", size);
 | 
					                qDebug("NFMModSource::pullAF: starve audio samples: size: %u", size);
 | 
				
			||||||
                sample = ((m_audioBuffer[size-1].l + m_audioBuffer[size-1].r) / 65536.0f) * m_settings.m_volumeFactor;
 | 
					                sample = ((m_audioBuffer[size-1].l + m_audioBuffer[size-1].r) / 65536.0f) * m_settings.m_volumeFactor;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case M17ModSettings::M17ModInputNone:
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        sample = 0.0f;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sample = 0.0f;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModSource::pullM17(Real& sample, bool& carrier)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // TODO
 | 
				
			||||||
 | 
					    carrier = false;
 | 
				
			||||||
 | 
					    sample = 0.0f;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void M17ModSource::pushFeedback(Real sample)
 | 
					void M17ModSource::pushFeedback(Real sample)
 | 
				
			||||||
@ -368,9 +398,9 @@ void M17ModSource::applySettings(const M17ModSettings& settings, bool force)
 | 
				
			|||||||
        m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
 | 
					        m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((settings.m_modAFInput != m_settings.m_modAFInput) || force)
 | 
					    if ((settings.m_audioType != m_settings.m_audioType) || force)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (settings.m_modAFInput == M17ModSettings::M17ModInputAudio) {
 | 
					        if (settings.m_audioType == M17ModSettings::AudioInput) {
 | 
				
			||||||
            connect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
 | 
					            connect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            disconnect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
 | 
					            disconnect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
 | 
				
			||||||
@ -416,3 +446,16 @@ void M17ModSource::handleAudio()
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void M17ModSource::sendPacket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (m_settings.m_packetType == M17ModSettings::PacketType::PacketSMS)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        M17ModProcessor::MsgSendSMS *msg = M17ModProcessor::MsgSendSMS::create(
 | 
				
			||||||
 | 
					            m_settings.m_sourceCall,
 | 
				
			||||||
 | 
					            m_settings.m_destCall,
 | 
				
			||||||
 | 
					            m_settings.m_smsText
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        m_processor->getInputMessageQueue()->push(msg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@
 | 
				
			|||||||
#include "m17modsettings.h"
 | 
					#include "m17modsettings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChannelAPI;
 | 
					class ChannelAPI;
 | 
				
			||||||
 | 
					class M17ModProcessor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class M17ModSource : public QObject, public ChannelSampleSource
 | 
					class M17ModSource : public QObject, public ChannelSampleSource
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -67,6 +68,8 @@ public:
 | 
				
			|||||||
    void applySettings(const M17ModSettings& settings, bool force = false);
 | 
					    void applySettings(const M17ModSettings& settings, bool force = false);
 | 
				
			||||||
    void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
 | 
					    void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void sendPacket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    int m_channelSampleRate;
 | 
					    int m_channelSampleRate;
 | 
				
			||||||
    int m_channelFrequencyOffset;
 | 
					    int m_channelFrequencyOffset;
 | 
				
			||||||
@ -115,6 +118,7 @@ private:
 | 
				
			|||||||
    Real m_levelSum;
 | 
					    Real m_levelSum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::ifstream *m_ifstream;
 | 
					    std::ifstream *m_ifstream;
 | 
				
			||||||
 | 
					    M17ModProcessor *m_processor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QMutex m_mutex;
 | 
					    QMutex m_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -122,7 +126,8 @@ private:
 | 
				
			|||||||
    static const float m_preemphasis;
 | 
					    static const float m_preemphasis;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void processOneSample(Complex& ci);
 | 
					    void processOneSample(Complex& ci);
 | 
				
			||||||
    void pullAF(Real& sample);
 | 
					    void pullAF(Real& sample, bool& carrier);
 | 
				
			||||||
 | 
					    void pullM17(Real& sample, bool& carrier);
 | 
				
			||||||
    void pullAudio(unsigned int nbSamples);
 | 
					    void pullAudio(unsigned int nbSamples);
 | 
				
			||||||
    void pushFeedback(Real sample);
 | 
					    void pushFeedback(Real sample);
 | 
				
			||||||
    void calculateLevel(Real& sample);
 | 
					    void calculateLevel(Real& sample);
 | 
				
			||||||
 | 
				
			|||||||
@ -8390,8 +8390,17 @@ margin-bottom: 20px;
 | 
				
			|||||||
    "audioDeviceName" : {
 | 
					    "audioDeviceName" : {
 | 
				
			||||||
      "type" : "string"
 | 
					      "type" : "string"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "modAFInput" : {
 | 
					    "m17Mode" : {
 | 
				
			||||||
      "type" : "integer"
 | 
					      "type" : "integer",
 | 
				
			||||||
 | 
					      "description" : "M17Mode"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "audioType" : {
 | 
				
			||||||
 | 
					      "type" : "integer",
 | 
				
			||||||
 | 
					      "description" : "AudioType"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "packetType" : {
 | 
				
			||||||
 | 
					      "type" : "integer",
 | 
				
			||||||
 | 
					      "description" : "PacketType"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "streamIndex" : {
 | 
					    "streamIndex" : {
 | 
				
			||||||
      "type" : "integer",
 | 
					      "type" : "integer",
 | 
				
			||||||
@ -56380,7 +56389,7 @@ except ApiException as e:
 | 
				
			|||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div id="generator">
 | 
					          <div id="generator">
 | 
				
			||||||
            <div class="content">
 | 
					            <div class="content">
 | 
				
			||||||
              Generated 2022-06-09T22:25:54.513+02:00
 | 
					              Generated 2022-06-10T22:26:56.056+02:00
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -26,8 +26,15 @@ M17ModSettings:
 | 
				
			|||||||
      type: string
 | 
					      type: string
 | 
				
			||||||
    audioDeviceName:
 | 
					    audioDeviceName:
 | 
				
			||||||
      type: string
 | 
					      type: string
 | 
				
			||||||
    modAFInput:
 | 
					    m17Mode:
 | 
				
			||||||
      type: integer
 | 
					      type: integer
 | 
				
			||||||
 | 
					      description: M17Mode
 | 
				
			||||||
 | 
					    audioType:
 | 
				
			||||||
 | 
					      type: integer
 | 
				
			||||||
 | 
					      description: AudioType
 | 
				
			||||||
 | 
					    packetType:
 | 
				
			||||||
 | 
					      type: integer
 | 
				
			||||||
 | 
					      description: PacketType
 | 
				
			||||||
    streamIndex:
 | 
					    streamIndex:
 | 
				
			||||||
      description: MIMO channel. Not relevant when connected to SI (single Rx).
 | 
					      description: MIMO channel. Not relevant when connected to SI (single Rx).
 | 
				
			||||||
      type: integer
 | 
					      type: integer
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@
 | 
				
			|||||||
    <file>bell_fill.png</file>
 | 
					    <file>bell_fill.png</file>
 | 
				
			||||||
    <file>bell_gradient.png</file>
 | 
					    <file>bell_gradient.png</file>
 | 
				
			||||||
    <file>bell_line.png</file>
 | 
					    <file>bell_line.png</file>
 | 
				
			||||||
 | 
					    <file>world.png</file>
 | 
				
			||||||
 | 
					    <file>sms.png</file>
 | 
				
			||||||
    <file>ruler.png</file>
 | 
					    <file>ruler.png</file>
 | 
				
			||||||
    <file>sort.png</file>
 | 
					    <file>sort.png</file>
 | 
				
			||||||
    <file>audio_mic.png</file>
 | 
					    <file>audio_mic.png</file>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								sdrgui/resources/sms.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sdrgui/resources/sms.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 821 B  | 
							
								
								
									
										
											BIN
										
									
								
								sdrgui/resources/world.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sdrgui/resources/world.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.6 KiB  | 
@ -26,8 +26,15 @@ M17ModSettings:
 | 
				
			|||||||
      type: string
 | 
					      type: string
 | 
				
			||||||
    audioDeviceName:
 | 
					    audioDeviceName:
 | 
				
			||||||
      type: string
 | 
					      type: string
 | 
				
			||||||
    modAFInput:
 | 
					    m17Mode:
 | 
				
			||||||
      type: integer
 | 
					      type: integer
 | 
				
			||||||
 | 
					      description: M17Mode
 | 
				
			||||||
 | 
					    audioType:
 | 
				
			||||||
 | 
					      type: integer
 | 
				
			||||||
 | 
					      description: AudioType
 | 
				
			||||||
 | 
					    packetType:
 | 
				
			||||||
 | 
					      type: integer
 | 
				
			||||||
 | 
					      description: PacketType
 | 
				
			||||||
    streamIndex:
 | 
					    streamIndex:
 | 
				
			||||||
      description: MIMO channel. Not relevant when connected to SI (single Rx).
 | 
					      description: MIMO channel. Not relevant when connected to SI (single Rx).
 | 
				
			||||||
      type: integer
 | 
					      type: integer
 | 
				
			||||||
 | 
				
			|||||||
@ -8390,8 +8390,17 @@ margin-bottom: 20px;
 | 
				
			|||||||
    "audioDeviceName" : {
 | 
					    "audioDeviceName" : {
 | 
				
			||||||
      "type" : "string"
 | 
					      "type" : "string"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "modAFInput" : {
 | 
					    "m17Mode" : {
 | 
				
			||||||
      "type" : "integer"
 | 
					      "type" : "integer",
 | 
				
			||||||
 | 
					      "description" : "M17Mode"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "audioType" : {
 | 
				
			||||||
 | 
					      "type" : "integer",
 | 
				
			||||||
 | 
					      "description" : "AudioType"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "packetType" : {
 | 
				
			||||||
 | 
					      "type" : "integer",
 | 
				
			||||||
 | 
					      "description" : "PacketType"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "streamIndex" : {
 | 
					    "streamIndex" : {
 | 
				
			||||||
      "type" : "integer",
 | 
					      "type" : "integer",
 | 
				
			||||||
@ -56380,7 +56389,7 @@ except ApiException as e:
 | 
				
			|||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div id="generator">
 | 
					          <div id="generator">
 | 
				
			||||||
            <div class="content">
 | 
					            <div class="content">
 | 
				
			||||||
              Generated 2022-06-09T22:25:54.513+02:00
 | 
					              Generated 2022-06-10T22:26:56.056+02:00
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -48,8 +48,12 @@ SWGM17ModSettings::SWGM17ModSettings() {
 | 
				
			|||||||
    m_title_isSet = false;
 | 
					    m_title_isSet = false;
 | 
				
			||||||
    audio_device_name = nullptr;
 | 
					    audio_device_name = nullptr;
 | 
				
			||||||
    m_audio_device_name_isSet = false;
 | 
					    m_audio_device_name_isSet = false;
 | 
				
			||||||
    mod_af_input = 0;
 | 
					    m17_mode = 0;
 | 
				
			||||||
    m_mod_af_input_isSet = false;
 | 
					    m_m17_mode_isSet = false;
 | 
				
			||||||
 | 
					    audio_type = 0;
 | 
				
			||||||
 | 
					    m_audio_type_isSet = false;
 | 
				
			||||||
 | 
					    packet_type = 0;
 | 
				
			||||||
 | 
					    m_packet_type_isSet = false;
 | 
				
			||||||
    stream_index = 0;
 | 
					    stream_index = 0;
 | 
				
			||||||
    m_stream_index_isSet = false;
 | 
					    m_stream_index_isSet = false;
 | 
				
			||||||
    use_reverse_api = 0;
 | 
					    use_reverse_api = 0;
 | 
				
			||||||
@ -94,8 +98,12 @@ SWGM17ModSettings::init() {
 | 
				
			|||||||
    m_title_isSet = false;
 | 
					    m_title_isSet = false;
 | 
				
			||||||
    audio_device_name = new QString("");
 | 
					    audio_device_name = new QString("");
 | 
				
			||||||
    m_audio_device_name_isSet = false;
 | 
					    m_audio_device_name_isSet = false;
 | 
				
			||||||
    mod_af_input = 0;
 | 
					    m17_mode = 0;
 | 
				
			||||||
    m_mod_af_input_isSet = false;
 | 
					    m_m17_mode_isSet = false;
 | 
				
			||||||
 | 
					    audio_type = 0;
 | 
				
			||||||
 | 
					    m_audio_type_isSet = false;
 | 
				
			||||||
 | 
					    packet_type = 0;
 | 
				
			||||||
 | 
					    m_packet_type_isSet = false;
 | 
				
			||||||
    stream_index = 0;
 | 
					    stream_index = 0;
 | 
				
			||||||
    m_stream_index_isSet = false;
 | 
					    m_stream_index_isSet = false;
 | 
				
			||||||
    use_reverse_api = 0;
 | 
					    use_reverse_api = 0;
 | 
				
			||||||
@ -133,6 +141,8 @@ SWGM17ModSettings::cleanup() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(reverse_api_address != nullptr) { 
 | 
					    if(reverse_api_address != nullptr) { 
 | 
				
			||||||
        delete reverse_api_address;
 | 
					        delete reverse_api_address;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -178,7 +188,11 @@ SWGM17ModSettings::fromJsonObject(QJsonObject &pJson) {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    ::SWGSDRangel::setValue(&audio_device_name, pJson["audioDeviceName"], "QString", "QString");
 | 
					    ::SWGSDRangel::setValue(&audio_device_name, pJson["audioDeviceName"], "QString", "QString");
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    ::SWGSDRangel::setValue(&mod_af_input, pJson["modAFInput"], "qint32", "");
 | 
					    ::SWGSDRangel::setValue(&m17_mode, pJson["m17Mode"], "qint32", "");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ::SWGSDRangel::setValue(&audio_type, pJson["audioType"], "qint32", "");
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ::SWGSDRangel::setValue(&packet_type, pJson["packetType"], "qint32", "");
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    ::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", "");
 | 
					    ::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", "");
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -242,8 +256,14 @@ SWGM17ModSettings::asJsonObject() {
 | 
				
			|||||||
    if(audio_device_name != nullptr && *audio_device_name != QString("")){
 | 
					    if(audio_device_name != nullptr && *audio_device_name != QString("")){
 | 
				
			||||||
        toJsonValue(QString("audioDeviceName"), audio_device_name, obj, QString("QString"));
 | 
					        toJsonValue(QString("audioDeviceName"), audio_device_name, obj, QString("QString"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(m_mod_af_input_isSet){
 | 
					    if(m_m17_mode_isSet){
 | 
				
			||||||
        obj->insert("modAFInput", QJsonValue(mod_af_input));
 | 
					        obj->insert("m17Mode", QJsonValue(m17_mode));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(m_audio_type_isSet){
 | 
				
			||||||
 | 
					        obj->insert("audioType", QJsonValue(audio_type));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(m_packet_type_isSet){
 | 
				
			||||||
 | 
					        obj->insert("packetType", QJsonValue(packet_type));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(m_stream_index_isSet){
 | 
					    if(m_stream_index_isSet){
 | 
				
			||||||
        obj->insert("streamIndex", QJsonValue(stream_index));
 | 
					        obj->insert("streamIndex", QJsonValue(stream_index));
 | 
				
			||||||
@ -374,13 +394,33 @@ SWGM17ModSettings::setAudioDeviceName(QString* audio_device_name) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qint32
 | 
					qint32
 | 
				
			||||||
SWGM17ModSettings::getModAfInput() {
 | 
					SWGM17ModSettings::getM17Mode() {
 | 
				
			||||||
    return mod_af_input;
 | 
					    return m17_mode;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
SWGM17ModSettings::setModAfInput(qint32 mod_af_input) {
 | 
					SWGM17ModSettings::setM17Mode(qint32 m17_mode) {
 | 
				
			||||||
    this->mod_af_input = mod_af_input;
 | 
					    this->m17_mode = m17_mode;
 | 
				
			||||||
    this->m_mod_af_input_isSet = true;
 | 
					    this->m_m17_mode_isSet = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qint32
 | 
				
			||||||
 | 
					SWGM17ModSettings::getAudioType() {
 | 
				
			||||||
 | 
					    return audio_type;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					SWGM17ModSettings::setAudioType(qint32 audio_type) {
 | 
				
			||||||
 | 
					    this->audio_type = audio_type;
 | 
				
			||||||
 | 
					    this->m_audio_type_isSet = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qint32
 | 
				
			||||||
 | 
					SWGM17ModSettings::getPacketType() {
 | 
				
			||||||
 | 
					    return packet_type;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					SWGM17ModSettings::setPacketType(qint32 packet_type) {
 | 
				
			||||||
 | 
					    this->packet_type = packet_type;
 | 
				
			||||||
 | 
					    this->m_packet_type_isSet = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qint32
 | 
					qint32
 | 
				
			||||||
@ -498,7 +538,13 @@ SWGM17ModSettings::isSet(){
 | 
				
			|||||||
        if(audio_device_name && *audio_device_name != QString("")){
 | 
					        if(audio_device_name && *audio_device_name != QString("")){
 | 
				
			||||||
            isObjectUpdated = true; break;
 | 
					            isObjectUpdated = true; break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(m_mod_af_input_isSet){
 | 
					        if(m_m17_mode_isSet){
 | 
				
			||||||
 | 
					            isObjectUpdated = true; break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(m_audio_type_isSet){
 | 
				
			||||||
 | 
					            isObjectUpdated = true; break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(m_packet_type_isSet){
 | 
				
			||||||
            isObjectUpdated = true; break;
 | 
					            isObjectUpdated = true; break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if(m_stream_index_isSet){
 | 
					        if(m_stream_index_isSet){
 | 
				
			||||||
 | 
				
			|||||||
@ -74,8 +74,14 @@ public:
 | 
				
			|||||||
    QString* getAudioDeviceName();
 | 
					    QString* getAudioDeviceName();
 | 
				
			||||||
    void setAudioDeviceName(QString* audio_device_name);
 | 
					    void setAudioDeviceName(QString* audio_device_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qint32 getModAfInput();
 | 
					    qint32 getM17Mode();
 | 
				
			||||||
    void setModAfInput(qint32 mod_af_input);
 | 
					    void setM17Mode(qint32 m17_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qint32 getAudioType();
 | 
				
			||||||
 | 
					    void setAudioType(qint32 audio_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qint32 getPacketType();
 | 
				
			||||||
 | 
					    void setPacketType(qint32 packet_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qint32 getStreamIndex();
 | 
					    qint32 getStreamIndex();
 | 
				
			||||||
    void setStreamIndex(qint32 stream_index);
 | 
					    void setStreamIndex(qint32 stream_index);
 | 
				
			||||||
@ -135,8 +141,14 @@ private:
 | 
				
			|||||||
    QString* audio_device_name;
 | 
					    QString* audio_device_name;
 | 
				
			||||||
    bool m_audio_device_name_isSet;
 | 
					    bool m_audio_device_name_isSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qint32 mod_af_input;
 | 
					    qint32 m17_mode;
 | 
				
			||||||
    bool m_mod_af_input_isSet;
 | 
					    bool m_m17_mode_isSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qint32 audio_type;
 | 
				
			||||||
 | 
					    bool m_audio_type_isSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qint32 packet_type;
 | 
				
			||||||
 | 
					    bool m_packet_type_isSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qint32 stream_index;
 | 
					    qint32 stream_index;
 | 
				
			||||||
    bool m_stream_index_isSet;
 | 
					    bool m_stream_index_isSet;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user