mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	FCD template.
This commit is contained in:
		
							parent
							
								
									fbae7c7f8e
								
							
						
					
					
						commit
						beda489261
					
				| @ -17,6 +17,10 @@ else() | |||||||
| 	find_package(LibRTLSDR) | 	find_package(LibRTLSDR) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
|  | if(LIBUSB_FOUND AND UNIX) | ||||||
|  | 	add_subdirectory(fcd) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| if(LIBUSB_FOUND AND LIBRTLSDR_FOUND) | if(LIBUSB_FOUND AND LIBRTLSDR_FOUND) | ||||||
| 	add_subdirectory(rtlsdr) | 	add_subdirectory(rtlsdr) | ||||||
| endif(LIBUSB_FOUND AND LIBRTLSDR_FOUND) | endif(LIBUSB_FOUND AND LIBRTLSDR_FOUND) | ||||||
|  | |||||||
							
								
								
									
										49
									
								
								plugins/samplesource/fcd/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								plugins/samplesource/fcd/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | project(fcd) | ||||||
|  | 
 | ||||||
|  | set(fcd_SOURCES | ||||||
|  | 	fcdgui.cpp | ||||||
|  | 	fcdinput.cpp | ||||||
|  | 	fcdplugin.cpp | ||||||
|  | 	fcdthread.cpp | ||||||
|  | 	fcdsource.cpp | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | set(rtlsdr_HEADERS | ||||||
|  | 	fcdgui.h | ||||||
|  | 	fcdinput.h | ||||||
|  | 	fcdplugin.h | ||||||
|  | 	fcdthread.h | ||||||
|  | 	fcdsource.h | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | set(fcd_FORMS | ||||||
|  | 	fcdgui.ui | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | include_directories( | ||||||
|  | 	. | ||||||
|  | 	${CMAKE_CURRENT_BINARY_DIR} | ||||||
|  | 	${CMAKE_SOURCE_DIR}/include | ||||||
|  | 	${CMAKE_SOURCE_DIR}/include-gpl | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | #include(${QT_USE_FILE}) | ||||||
|  | add_definitions(${QT_DEFINITIONS}) | ||||||
|  | add_definitions(-DQT_PLUGIN) | ||||||
|  | add_definitions(-DQT_SHARED) | ||||||
|  | 
 | ||||||
|  | #qt4_wrap_cpp(fcd_HEADERS_MOC ${fcd_HEADERS}) | ||||||
|  | qt5_wrap_ui(fcd_FORMS_HEADERS ${fcd_FORMS}) | ||||||
|  | 
 | ||||||
|  | add_library(inputfcd SHARED | ||||||
|  | 	${fcd_SOURCES} | ||||||
|  | 	${fcd_HEADERS_MOC} | ||||||
|  | 	${fcd_FORMS_HEADERS} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | target_link_libraries(inputfcd | ||||||
|  | 	${QT_LIBRARIES} | ||||||
|  | 	sdrbase | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | qt5_use_modules(inputfcd Core Widgets OpenGL Multimedia) | ||||||
							
								
								
									
										137
									
								
								plugins/samplesource/fcd/fcdgui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								plugins/samplesource/fcd/fcdgui.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,137 @@ | |||||||
|  | #include "fcdgui.h" | ||||||
|  | #include "ui_fcdgui.h" | ||||||
|  | #include "plugin/pluginapi.h" | ||||||
|  | 
 | ||||||
|  | FCDGui::FCDGui(PluginAPI* pluginAPI, QWidget* parent) : | ||||||
|  | 	QWidget(parent), | ||||||
|  | 	ui(new Ui::FCDGui), | ||||||
|  | 	m_pluginAPI(pluginAPI), | ||||||
|  | 	m_settings(), | ||||||
|  | 	m_sampleSource(NULL) | ||||||
|  | { | ||||||
|  | 	ui->setupUi(this); | ||||||
|  | 	ui->centerFrequency->setValueRange(7, 420000U, 1900000U); | ||||||
|  | 	connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); | ||||||
|  | 	displaySettings(); | ||||||
|  | 
 | ||||||
|  | 	m_sampleSource = new FCDInput(m_pluginAPI->getMainWindowMessageQueue()); | ||||||
|  | 	m_pluginAPI->setSampleSource(m_sampleSource); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDGui::~FCDGui() | ||||||
|  | { | ||||||
|  | 	delete ui; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::destroy() | ||||||
|  | { | ||||||
|  | 	delete this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::setName(const QString& name) | ||||||
|  | { | ||||||
|  | 	setObjectName(name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::resetToDefaults() | ||||||
|  | { | ||||||
|  | 	m_generalSettings.resetToDefaults(); | ||||||
|  | 	m_settings.resetToDefaults(); | ||||||
|  | 	displaySettings(); | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QByteArray FCDGui::serializeGeneral() const | ||||||
|  | { | ||||||
|  | 	return m_generalSettings.serialize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDGui::deserializeGeneral(const QByteArray&data) | ||||||
|  | { | ||||||
|  | 	if(m_generalSettings.deserialize(data)) { | ||||||
|  | 		displaySettings(); | ||||||
|  | 		sendSettings(); | ||||||
|  | 		return true; | ||||||
|  | 	} else { | ||||||
|  | 		resetToDefaults(); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | quint64 FCDGui::getCenterFrequency() const | ||||||
|  | { | ||||||
|  | 	return m_generalSettings.m_centerFrequency; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QByteArray FCDGui::serialize() const | ||||||
|  | { | ||||||
|  | 	return m_settings.serialize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDGui::deserialize(const QByteArray& data) | ||||||
|  | { | ||||||
|  | 	if(m_settings.deserialize(data)) { | ||||||
|  | 		displaySettings(); | ||||||
|  | 		sendSettings(); | ||||||
|  | 		return true; | ||||||
|  | 	} else { | ||||||
|  | 		resetToDefaults(); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDGui::handleMessage(Message* message) | ||||||
|  | { | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::displaySettings() | ||||||
|  | { | ||||||
|  | 	ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::sendSettings() | ||||||
|  | { | ||||||
|  | 	if(!m_updateTimer.isActive()) | ||||||
|  | 		m_updateTimer.start(100); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::on_centerFrequency_changed(quint64 value) | ||||||
|  | { | ||||||
|  | 	m_generalSettings.m_centerFrequency = value * 1000; | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #if 0 | ||||||
|  | void FCDGui::on_gain_valueChanged(int value) | ||||||
|  | { | ||||||
|  | 	if(value > (int)m_gains.size()) | ||||||
|  | 		return; | ||||||
|  | 	int gain = m_gains[value]; | ||||||
|  | 	ui->gainText->setText(tr("%1.%2").arg(gain / 10).arg(abs(gain % 10))); | ||||||
|  | 	m_settings.m_gain = gain; | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | void FCDGui::updateHardware() | ||||||
|  | { | ||||||
|  | 	FCDInput::MsgConfigureFCD* message = FCDInput::MsgConfigureFCD::create(m_generalSettings, m_settings); | ||||||
|  | 	message->submit(m_pluginAPI->getDSPEngineMessageQueue()); | ||||||
|  | 	m_updateTimer.stop(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::on_checkBox_stateChanged(int state) { | ||||||
|  | 	if (state == Qt::Checked){ | ||||||
|  | 		ui->centerFrequency->setValueRange(7, 150U, 240000U); | ||||||
|  | 		ui->centerFrequency->setValue(7000); | ||||||
|  | 		m_generalSettings.m_centerFrequency = 7000 * 1000; | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		ui->centerFrequency->setValueRange(7, 420000U, 1900000U); | ||||||
|  | 		ui->centerFrequency->setValue(434450); | ||||||
|  | 		m_generalSettings.m_centerFrequency = 434450 * 1000; | ||||||
|  | 	} | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										53
									
								
								plugins/samplesource/fcd/fcdgui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								plugins/samplesource/fcd/fcdgui.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | #ifndef INCLUDE_FCDGUI_H | ||||||
|  | #define INCLUDE_FCDGUI_H | ||||||
|  | 
 | ||||||
|  | #include <QTimer> | ||||||
|  | #include "plugin/plugingui.h" | ||||||
|  | #include "fcdinput.h" | ||||||
|  | 
 | ||||||
|  | class PluginAPI; | ||||||
|  | 
 | ||||||
|  | namespace Ui { | ||||||
|  | 	class FCDGui; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class FCDGui : public QWidget, public PluginGUI { | ||||||
|  | 	Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	explicit FCDGui(PluginAPI* pluginAPI, QWidget* parent = NULL); | ||||||
|  | 	~FCDGui(); | ||||||
|  | 	void destroy(); | ||||||
|  | 
 | ||||||
|  | 	void setName(const QString& name); | ||||||
|  | 
 | ||||||
|  | 	void resetToDefaults(); | ||||||
|  | 	QByteArray serializeGeneral() const; | ||||||
|  | 	bool deserializeGeneral(const QByteArray&data); | ||||||
|  | 	quint64 getCenterFrequency() const; | ||||||
|  | 	QByteArray serialize() const; | ||||||
|  | 	bool deserialize(const QByteArray& data); | ||||||
|  | 	bool handleMessage(Message* message); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	Ui::FCDGui* ui; | ||||||
|  | 
 | ||||||
|  | 	PluginAPI* m_pluginAPI; | ||||||
|  | 	SampleSource::GeneralSettings m_generalSettings; | ||||||
|  | 	FCDInput::Settings m_settings; | ||||||
|  | 	QTimer m_updateTimer; | ||||||
|  | 	std::vector<int> m_gains; | ||||||
|  | 	SampleSource* m_sampleSource; | ||||||
|  | 
 | ||||||
|  | 	void displaySettings(); | ||||||
|  | 	void sendSettings(); | ||||||
|  | 
 | ||||||
|  | private slots: | ||||||
|  | 	void on_centerFrequency_changed(quint64 value); | ||||||
|  | 	//void on_gain_valueChanged(int value);
 | ||||||
|  | 	//void on_samplerate_valueChanged(int value);
 | ||||||
|  | 	void on_checkBox_stateChanged(int state); | ||||||
|  | 	void updateHardware(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // INCLUDE_FCDGUI_H
 | ||||||
							
								
								
									
										260
									
								
								plugins/samplesource/fcd/fcdgui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								plugins/samplesource/fcd/fcdgui.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,260 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <ui version="4.0"> | ||||||
|  |  <class>FCDGui</class> | ||||||
|  |  <widget class="QWidget" name="FCDGui"> | ||||||
|  |   <property name="geometry"> | ||||||
|  |    <rect> | ||||||
|  |     <x>0</x> | ||||||
|  |     <y>0</y> | ||||||
|  |     <width>132</width> | ||||||
|  |     <height>119</height> | ||||||
|  |    </rect> | ||||||
|  |   </property> | ||||||
|  |   <property name="sizePolicy"> | ||||||
|  |    <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> | ||||||
|  |     <horstretch>0</horstretch> | ||||||
|  |     <verstretch>0</verstretch> | ||||||
|  |    </sizepolicy> | ||||||
|  |   </property> | ||||||
|  |   <property name="windowTitle"> | ||||||
|  |    <string>FunCubeDongle</string> | ||||||
|  |   </property> | ||||||
|  |   <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|  |    <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_3"> | ||||||
|  |      <item> | ||||||
|  |       <spacer name="horizontalSpacer"> | ||||||
|  |        <property name="orientation"> | ||||||
|  |         <enum>Qt::Horizontal</enum> | ||||||
|  |        </property> | ||||||
|  |        <property name="sizeHint" stdset="0"> | ||||||
|  |         <size> | ||||||
|  |          <width>0</width> | ||||||
|  |          <height>0</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |       </spacer> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <widget class="ValueDial" name="centerFrequency" native="true"> | ||||||
|  |        <property name="sizePolicy"> | ||||||
|  |         <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||||||
|  |          <horstretch>0</horstretch> | ||||||
|  |          <verstretch>0</verstretch> | ||||||
|  |         </sizepolicy> | ||||||
|  |        </property> | ||||||
|  |        <property name="minimumSize"> | ||||||
|  |         <size> | ||||||
|  |          <width>32</width> | ||||||
|  |          <height>16</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |        <property name="font"> | ||||||
|  |         <font> | ||||||
|  |          <family>Monospace</family> | ||||||
|  |          <pointsize>20</pointsize> | ||||||
|  |         </font> | ||||||
|  |        </property> | ||||||
|  |        <property name="focusPolicy"> | ||||||
|  |         <enum>Qt::StrongFocus</enum> | ||||||
|  |        </property> | ||||||
|  |        <property name="toolTip"> | ||||||
|  |         <string>Tuner center frequency in kHz</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <spacer name="horizontalSpacer_2"> | ||||||
|  |        <property name="orientation"> | ||||||
|  |         <enum>Qt::Horizontal</enum> | ||||||
|  |        </property> | ||||||
|  |        <property name="sizeHint" stdset="0"> | ||||||
|  |         <size> | ||||||
|  |          <width>0</width> | ||||||
|  |          <height>0</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |       </spacer> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="Line" name="line_4"> | ||||||
|  |      <property name="orientation"> | ||||||
|  |       <enum>Qt::Horizontal</enum> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |    <!--item> | ||||||
|  |     <layout class="QGridLayout" name="gridLayout_3"> | ||||||
|  |      <property name="spacing"> | ||||||
|  |       <number>3</number> | ||||||
|  |      </property> | ||||||
|  |      <item row="0" column="1"> | ||||||
|  |       <widget class="QSlider" name="samplerate"> | ||||||
|  |        <property name="toolTip"> | ||||||
|  |         <string>Device Samplerate</string> | ||||||
|  |        </property> | ||||||
|  |        <property name="maximum"> | ||||||
|  |         <number>4</number> | ||||||
|  |        </property> | ||||||
|  |        <property name="pageStep"> | ||||||
|  |         <number>1</number> | ||||||
|  |        </property> | ||||||
|  |        <property name="orientation"> | ||||||
|  |         <enum>Qt::Horizontal</enum> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item row="0" column="0"> | ||||||
|  |       <widget class="QLabel" name="label_12"> | ||||||
|  |        <property name="sizePolicy"> | ||||||
|  |         <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> | ||||||
|  |          <horstretch>0</horstretch> | ||||||
|  |          <verstretch>0</verstretch> | ||||||
|  |         </sizepolicy> | ||||||
|  |        </property> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>Rate</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item row="0" column="2"> | ||||||
|  |       <widget class="QLabel" name="samplerateText"> | ||||||
|  |        <property name="minimumSize"> | ||||||
|  |         <size> | ||||||
|  |          <width>40</width> | ||||||
|  |          <height>0</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>288k</string> | ||||||
|  |        </property> | ||||||
|  |        <property name="alignment"> | ||||||
|  |         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="Line" name="line_3"> | ||||||
|  |      <property name="orientation"> | ||||||
|  |       <enum>Qt::Horizontal</enum> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <layout class="QGridLayout" name="gridLayout_2"> | ||||||
|  |      <property name="spacing"> | ||||||
|  |       <number>3</number> | ||||||
|  |      </property> | ||||||
|  |      <item row="0" column="0"> | ||||||
|  |       <widget class="QLabel" name="label_11"> | ||||||
|  |        <property name="sizePolicy"> | ||||||
|  |         <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> | ||||||
|  |          <horstretch>0</horstretch> | ||||||
|  |          <verstretch>0</verstretch> | ||||||
|  |         </sizepolicy> | ||||||
|  |        </property> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>Gain</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item row="0" column="1"> | ||||||
|  |       <widget class="QSlider" name="gain"> | ||||||
|  |        <property name="enabled"> | ||||||
|  |         <bool>false</bool> | ||||||
|  |        </property> | ||||||
|  |        <property name="toolTip"> | ||||||
|  |         <string>LNA amplification</string> | ||||||
|  |        </property> | ||||||
|  |        <property name="maximum"> | ||||||
|  |         <number>0</number> | ||||||
|  |        </property> | ||||||
|  |        <property name="pageStep"> | ||||||
|  |         <number>1</number> | ||||||
|  |        </property> | ||||||
|  |        <property name="orientation"> | ||||||
|  |         <enum>Qt::Horizontal</enum> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item row="0" column="2"> | ||||||
|  |       <widget class="QLabel" name="gainText"> | ||||||
|  |        <property name="minimumSize"> | ||||||
|  |         <size> | ||||||
|  |          <width>40</width> | ||||||
|  |          <height>0</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>...</string> | ||||||
|  |        </property> | ||||||
|  |        <property name="alignment"> | ||||||
|  |         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="Line" name="line"> | ||||||
|  |      <property name="orientation"> | ||||||
|  |       <enum>Qt::Horizontal</enum> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item--> | ||||||
|  |    <item> | ||||||
|  |     <layout class="QHBoxLayout" name="horizontalLayout"> | ||||||
|  |      <item> | ||||||
|  |       <widget class="QCheckBox" name="checkBox"> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>Low Range</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <spacer name="horizontalSpacer_3"> | ||||||
|  |        <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> | ||||||
|  |   </layout> | ||||||
|  |  </widget> | ||||||
|  |  <customwidgets> | ||||||
|  |   <customwidget> | ||||||
|  |    <class>ValueDial</class> | ||||||
|  |    <extends>QWidget</extends> | ||||||
|  |    <header>gui/valuedial.h</header> | ||||||
|  |    <container>1</container> | ||||||
|  |   </customwidget> | ||||||
|  |  </customwidgets> | ||||||
|  |  <resources/> | ||||||
|  |  <connections/> | ||||||
|  | </ui> | ||||||
							
								
								
									
										135
									
								
								plugins/samplesource/fcd/fcdinput.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								plugins/samplesource/fcd/fcdinput.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,135 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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 <string.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include "fcdinput.h" | ||||||
|  | #include "fcdthread.h" | ||||||
|  | #include "fcdgui.h" | ||||||
|  | #include "util/simpleserializer.h" | ||||||
|  | 
 | ||||||
|  | MESSAGE_CLASS_DEFINITION(FCDInput::MsgConfigureFCD, Message) | ||||||
|  | //MESSAGE_CLASS_DEFINITION(FCDInput::MsgReportFCD, Message)
 | ||||||
|  | 
 | ||||||
|  | FCDInput::Settings::Settings() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::Settings::resetToDefaults() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QByteArray FCDInput::Settings::serialize() const | ||||||
|  | { | ||||||
|  | 	SimpleSerializer s(1); | ||||||
|  | 	return s.final(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::Settings::deserialize(const QByteArray& data) | ||||||
|  | { | ||||||
|  | 	resetToDefaults(); | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDInput::FCDInput(MessageQueue* msgQueueToGUI) : | ||||||
|  | 	SampleSource(msgQueueToGUI), | ||||||
|  | 	m_settings(), | ||||||
|  | 	m_FCDThread(NULL), | ||||||
|  | 	m_deviceDescription() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDInput::~FCDInput() | ||||||
|  | { | ||||||
|  | 	stopInput(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::startInput(int device) | ||||||
|  | { | ||||||
|  | 	QMutexLocker mutexLocker(&m_mutex); | ||||||
|  | 
 | ||||||
|  | 	if(m_FCDThread) | ||||||
|  | 		return false; | ||||||
|  | 
 | ||||||
|  | 	if(!m_sampleFifo.setSize(4096*16)) { | ||||||
|  | 		qCritical("Could not allocate SampleFifo"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if((m_FCDThread = new FCDThread(&m_sampleFifo)) == NULL) { | ||||||
|  | 		qFatal("out of memory"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	m_deviceDescription = QString("Funcube Dongle"); | ||||||
|  | 
 | ||||||
|  | 	qDebug("FCDInput: start"); | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::stopInput() | ||||||
|  | { | ||||||
|  | 	QMutexLocker mutexLocker(&m_mutex); | ||||||
|  | 
 | ||||||
|  | 	if(m_FCDThread) { | ||||||
|  | 		m_FCDThread->stopWork(); | ||||||
|  | 		// wait for thread to quit ?
 | ||||||
|  | 		delete m_FCDThread; | ||||||
|  | 		m_FCDThread = NULL; | ||||||
|  | 	} | ||||||
|  | 	m_deviceDescription.clear(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const QString& FCDInput::getDeviceDescription() const | ||||||
|  | { | ||||||
|  | 	return m_deviceDescription; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int FCDInput::getSampleRate() const | ||||||
|  | { | ||||||
|  | 	return 192000; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | quint64 FCDInput::getCenterFrequency() const | ||||||
|  | { | ||||||
|  | 	return m_generalSettings.m_centerFrequency; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::handleMessage(Message* message) | ||||||
|  | { | ||||||
|  | 	if(MsgConfigureFCD::match(message)) { | ||||||
|  | 		MsgConfigureFCD* conf = (MsgConfigureFCD*)message; | ||||||
|  | 		if(!applySettings(conf->getGeneralSettings(), conf->getSettings(), false)) | ||||||
|  | 			qDebug("FCD config error"); | ||||||
|  | 		message->completed(); | ||||||
|  | 		return true; | ||||||
|  | 	} else { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force) | ||||||
|  | { | ||||||
|  | 	QMutexLocker mutexLocker(&m_mutex); | ||||||
|  | 
 | ||||||
|  | 	if((m_generalSettings.m_centerFrequency != generalSettings.m_centerFrequency) || force) { | ||||||
|  | 		m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency; | ||||||
|  | 		if(m_FCDThread) | ||||||
|  | 			m_FCDThread->set_center_freq( (double)(generalSettings.m_centerFrequency) ); | ||||||
|  | 	}	 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
							
								
								
									
										83
									
								
								plugins/samplesource/fcd/fcdinput.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								plugins/samplesource/fcd/fcdinput.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,83 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #ifndef INCLUDE_FCDINPUT_H | ||||||
|  | #define INCLUDE_FCDINPUT_H | ||||||
|  | 
 | ||||||
|  | #include "dsp/samplesource/samplesource.h" | ||||||
|  | #include <QString> | ||||||
|  | 
 | ||||||
|  | struct fcd_buffer { | ||||||
|  | 	void *start; | ||||||
|  | 	size_t length; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class FCDThread; | ||||||
|  | 
 | ||||||
|  | class FCDInput : public SampleSource { | ||||||
|  | public: | ||||||
|  | 	struct Settings { | ||||||
|  | 		Settings(); | ||||||
|  | 		void resetToDefaults(); | ||||||
|  | 		QByteArray serialize() const; | ||||||
|  | 		bool deserialize(const QByteArray& data); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	class MsgConfigureFCD : public Message { | ||||||
|  | 		MESSAGE_CLASS_DECLARATION | ||||||
|  | 
 | ||||||
|  | 	public: | ||||||
|  | 		const GeneralSettings& getGeneralSettings() const { return m_generalSettings; } | ||||||
|  | 		const Settings& getSettings() const { return m_settings; } | ||||||
|  | 
 | ||||||
|  | 		static MsgConfigureFCD* create(const GeneralSettings& generalSettings, const Settings& settings) | ||||||
|  | 		{ | ||||||
|  | 			return new MsgConfigureFCD(generalSettings, settings); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	private: | ||||||
|  | 		GeneralSettings m_generalSettings; | ||||||
|  | 		Settings m_settings; | ||||||
|  | 
 | ||||||
|  | 		MsgConfigureFCD(const GeneralSettings& generalSettings, const Settings& settings) : | ||||||
|  | 			Message(), | ||||||
|  | 			m_generalSettings(generalSettings), | ||||||
|  | 			m_settings(settings) | ||||||
|  | 		{ } | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	FCDInput(MessageQueue* msgQueueToGUI); | ||||||
|  | 	~FCDInput(); | ||||||
|  | 
 | ||||||
|  | 	bool startInput(int device); | ||||||
|  | 	void stopInput(); | ||||||
|  | 
 | ||||||
|  | 	const QString& getDeviceDescription() const; | ||||||
|  | 	int getSampleRate() const; | ||||||
|  | 	quint64 getCenterFrequency() const; | ||||||
|  | 	bool handleMessage(Message* message); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	QMutex m_mutex; | ||||||
|  | 	Settings m_settings; | ||||||
|  | 	FCDThread* m_FCDThread; | ||||||
|  | 	QString m_deviceDescription; | ||||||
|  | 	bool applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // INCLUDE_FCD_H
 | ||||||
							
								
								
									
										55
									
								
								plugins/samplesource/fcd/fcdplugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								plugins/samplesource/fcd/fcdplugin.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | |||||||
|  | #include <QtPlugin> | ||||||
|  | #include <QAction> | ||||||
|  | #include "plugin/pluginapi.h" | ||||||
|  | #include "util/simpleserializer.h" | ||||||
|  | #include "fcdplugin.h" | ||||||
|  | #include "fcdgui.h" | ||||||
|  | 
 | ||||||
|  | const PluginDescriptor FCDPlugin::m_pluginDescriptor = { | ||||||
|  | 	QString("FunCube Input"), | ||||||
|  | 	QString("---"), | ||||||
|  | 	QString("(c) John Greb"), | ||||||
|  | 	QString("http://funcubedongle.com"), | ||||||
|  | 	true, | ||||||
|  | 	QString("___________") | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | FCDPlugin::FCDPlugin(QObject* parent) : | ||||||
|  | 	QObject(parent) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const PluginDescriptor& FCDPlugin::getPluginDescriptor() const | ||||||
|  | { | ||||||
|  | 	return m_pluginDescriptor; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDPlugin::initPlugin(PluginAPI* pluginAPI) | ||||||
|  | { | ||||||
|  | 	m_pluginAPI = pluginAPI; | ||||||
|  | 
 | ||||||
|  | 	m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.fcd", this); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PluginInterface::SampleSourceDevices FCDPlugin::enumSampleSources() | ||||||
|  | { | ||||||
|  | 	SampleSourceDevices result; | ||||||
|  | 
 | ||||||
|  | 	QString displayedName(QString("Funcube Dongle #1")); | ||||||
|  | 	SimpleSerializer s(1); | ||||||
|  | 	s.writeS32(1, 0); | ||||||
|  | 	result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.fcd", s.final())); | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PluginGUI* FCDPlugin::createSampleSource(const QString& sourceName, const QByteArray& address) | ||||||
|  | { | ||||||
|  | 	if(sourceName == "org.osmocom.sdr.samplesource.fcd") { | ||||||
|  | 		FCDGui* gui = new FCDGui(m_pluginAPI); | ||||||
|  | 		m_pluginAPI->setInputGUI(gui); | ||||||
|  | 		return gui; | ||||||
|  | 	} else { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								plugins/samplesource/fcd/fcdplugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								plugins/samplesource/fcd/fcdplugin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | #ifndef INCLUDE_FCDPLUGIN_H | ||||||
|  | #define INCLUDE_FCDPLUGIN_H | ||||||
|  | 
 | ||||||
|  | #include <QObject> | ||||||
|  | #include "plugin/plugininterface.h" | ||||||
|  | 
 | ||||||
|  | class FCDPlugin : public QObject, PluginInterface { | ||||||
|  | 	Q_OBJECT | ||||||
|  | 	Q_INTERFACES(PluginInterface) | ||||||
|  | 	Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.fcd") | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	explicit FCDPlugin(QObject* parent = NULL); | ||||||
|  | 
 | ||||||
|  | 	const PluginDescriptor& getPluginDescriptor() const; | ||||||
|  | 	void initPlugin(PluginAPI* pluginAPI); | ||||||
|  | 
 | ||||||
|  | 	SampleSourceDevices enumSampleSources(); | ||||||
|  | 	PluginGUI* createSampleSource(const QString& sourceName, const QByteArray& address); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	static const PluginDescriptor m_pluginDescriptor; | ||||||
|  | 
 | ||||||
|  | 	PluginAPI* m_pluginAPI; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // INCLUDE_FCDPLUGIN_H
 | ||||||
							
								
								
									
										0
									
								
								plugins/samplesource/fcd/fcdsource.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								plugins/samplesource/fcd/fcdsource.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										54
									
								
								plugins/samplesource/fcd/fcdthread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								plugins/samplesource/fcd/fcdthread.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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 <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include "fcdthread.h" | ||||||
|  | #include "dsp/samplefifo.h" | ||||||
|  | 
 | ||||||
|  | FCDThread::FCDThread(SampleFifo* sampleFifo, QObject* parent) : | ||||||
|  | 	QThread(parent), | ||||||
|  | 	m_running(false), | ||||||
|  | 	m_convertBuffer(BLOCKSIZE), | ||||||
|  | 	m_sampleFifo(sampleFifo) | ||||||
|  | { | ||||||
|  | 	start(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDThread::~FCDThread() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDThread::stopWork() | ||||||
|  | { | ||||||
|  | 	m_running = false; | ||||||
|  | 	wait(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDThread::run() | ||||||
|  | { | ||||||
|  | 	m_running = true; | ||||||
|  | 	OpenSource("/dev/dsp"); | ||||||
|  | 	if (fd < 0) | ||||||
|  |                 return; | ||||||
|  | 
 | ||||||
|  | 	while(m_running) { | ||||||
|  | 		work(BLOCKSIZE); | ||||||
|  | 	} | ||||||
|  | 	CloseSource(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										60
									
								
								plugins/samplesource/fcd/fcdthread.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								plugins/samplesource/fcd/fcdthread.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // 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/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #ifndef INCLUDE_FCDTHREAD_H | ||||||
|  | #define INCLUDE_FCDTHREAD_H | ||||||
|  | 
 | ||||||
|  | #include <QThread> | ||||||
|  | #include <QMutex> | ||||||
|  | #include <QWaitCondition> | ||||||
|  | #include "dsp/samplefifo.h" | ||||||
|  | #include "dsp/inthalfbandfilter.h" | ||||||
|  | 
 | ||||||
|  | #define SAMPLERATE 192000 | ||||||
|  | #define BLOCKSIZE 8192 | ||||||
|  | 
 | ||||||
|  | class FCDThread : public QThread { | ||||||
|  | 	Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	FCDThread(SampleFifo* sampleFifo, QObject* parent = NULL); | ||||||
|  | 	~FCDThread(); | ||||||
|  | 
 | ||||||
|  | 	void stopWork(); | ||||||
|  | 	void OpenSource(const char *filename); | ||||||
|  | 	void CloseSource(); | ||||||
|  | 	void set_center_freq(double freq); | ||||||
|  | 	int  work(int n_items); | ||||||
|  | private: | ||||||
|  | 	int fd; | ||||||
|  | 	struct fcd_buffer *buffers; | ||||||
|  | 	unsigned int n_buffers; | ||||||
|  | 	void *recebuf_ptr; | ||||||
|  | 	unsigned int recebuf_len; | ||||||
|  | 	unsigned int recebuf_mmap_index; | ||||||
|  | 
 | ||||||
|  | 	QMutex m_startWaitMutex; | ||||||
|  | 	QWaitCondition m_startWaiter; | ||||||
|  | 	bool m_running; | ||||||
|  | 
 | ||||||
|  | 	SampleVector m_convertBuffer; | ||||||
|  | 	SampleFifo* m_sampleFifo; | ||||||
|  | 
 | ||||||
|  | 	void run(); | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | #endif // INCLUDE_FCDTHREAD_H
 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user