mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 13:11:20 -05:00 
			
		
		
		
	SDRdaemonSink plugin (1)
This commit is contained in:
		
							parent
							
								
									1239579266
								
							
						
					
					
						commit
						497ae3651e
					
				@ -17,10 +17,18 @@ if(LIBUSB_FOUND AND LIMESUITE_FOUND)
 | 
			
		||||
    add_subdirectory(limesdroutput)
 | 
			
		||||
endif(LIBUSB_FOUND AND LIMESUITE_FOUND)
 | 
			
		||||
 | 
			
		||||
find_package(CM256cc)
 | 
			
		||||
if(CM256CC_FOUND AND LIBNANOMSG_FOUND)
 | 
			
		||||
    add_subdirectory(sdrdaemonsink)
 | 
			
		||||
endif(CM256CC_FOUND AND LIBNANOMSG_FOUND)
 | 
			
		||||
 | 
			
		||||
if (BUILD_DEBIAN)
 | 
			
		||||
    add_subdirectory(bladerfoutput)
 | 
			
		||||
    add_subdirectory(hackrfoutput)
 | 
			
		||||
    add_subdirectory(limesdroutput)
 | 
			
		||||
    if (LIBNANOMSG_FOUND)
 | 
			
		||||
        add_subdirectory(sdrdaemonsink)
 | 
			
		||||
    endif (LIBNANOMSG_FOUND)    
 | 
			
		||||
endif (BUILD_DEBIAN)
 | 
			
		||||
 | 
			
		||||
add_subdirectory(filesink)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								plugins/samplesink/sdrdaemonsink/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								plugins/samplesink/sdrdaemonsink/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
project(sdrdaemonsink)
 | 
			
		||||
 | 
			
		||||
set(sdrdaemonsink_SOURCES
 | 
			
		||||
#	sdrdaemonsinkgui.cpp
 | 
			
		||||
#	sdrdaemonsinkoutput.cpp
 | 
			
		||||
#	sdrdaemonsinkplugin.cpp
 | 
			
		||||
	sdrdaemonsinksettings.cpp
 | 
			
		||||
#	sdrdaemonsinkthread.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(sdrdaemonsink_HEADERS
 | 
			
		||||
#	sdrdaemonsinkgui.h
 | 
			
		||||
#	sdrdaemonsinkoutput.h
 | 
			
		||||
#	sdrdaemonsinkplugin.h
 | 
			
		||||
	sdrdaemonsinksettings.h
 | 
			
		||||
#	sdrdaemonsinkthread.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
#set(sdrdaemonsink_FORMS
 | 
			
		||||
#	sdrdaemonsinkgui.ui
 | 
			
		||||
#)
 | 
			
		||||
 | 
			
		||||
include_directories(
 | 
			
		||||
	.
 | 
			
		||||
	${CMAKE_CURRENT_BINARY_DIR}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_definitions(${QT_DEFINITIONS})
 | 
			
		||||
add_definitions(-DQT_PLUGIN)
 | 
			
		||||
add_definitions(-DQT_SHARED)
 | 
			
		||||
 | 
			
		||||
#qt5_wrap_ui(sdrdaemonsink_FORMS_HEADERS ${sdrdaemonsink_FORMS})
 | 
			
		||||
 | 
			
		||||
add_library(outputsdrdaemonsink SHARED
 | 
			
		||||
	${sdrdaemonsink_SOURCES}
 | 
			
		||||
	${sdrdaemonsink_HEADERS_MOC}
 | 
			
		||||
	${sdrdaemonsink_FORMS_HEADERS}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(outputsdrdaemonsink
 | 
			
		||||
	${QT_LIBRARIES}
 | 
			
		||||
	sdrbase
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
qt5_use_modules(outputsdrdaemonsink Core Widgets)
 | 
			
		||||
 | 
			
		||||
install(TARGETS outputsdrdaemonsink DESTINATION lib/plugins/samplesink)
 | 
			
		||||
							
								
								
									
										41
									
								
								plugins/samplesink/sdrdaemonsink/filesink.pro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								plugins/samplesink/sdrdaemonsink/filesink.pro
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
#--------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
# Pro file for Android and Windows builds with Qt Creator
 | 
			
		||||
#
 | 
			
		||||
#--------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
TEMPLATE = lib
 | 
			
		||||
CONFIG += plugin
 | 
			
		||||
 | 
			
		||||
QT += core gui widgets multimedia opengl
 | 
			
		||||
 | 
			
		||||
TARGET = outputfilesink
 | 
			
		||||
 | 
			
		||||
DEFINES += USE_SSE2=1
 | 
			
		||||
QMAKE_CXXFLAGS += -msse2
 | 
			
		||||
DEFINES += USE_SSE4_1=1
 | 
			
		||||
QMAKE_CXXFLAGS += -msse4.1
 | 
			
		||||
 | 
			
		||||
INCLUDEPATH += $$PWD
 | 
			
		||||
INCLUDEPATH += ../../../sdrbase
 | 
			
		||||
 | 
			
		||||
CONFIG(Release):build_subdir = release
 | 
			
		||||
CONFIG(Debug):build_subdir = debug
 | 
			
		||||
 | 
			
		||||
SOURCES += filesinkgui.cpp\
 | 
			
		||||
	filesinkoutput.cpp\
 | 
			
		||||
	filesinkplugin.cpp\
 | 
			
		||||
	filesinksettings.cpp\
 | 
			
		||||
	filesinkthread.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS += filesinkgui.h\
 | 
			
		||||
	filesinkoutput.h\
 | 
			
		||||
	filesinkplugin.h\
 | 
			
		||||
	filesinksettings.h\
 | 
			
		||||
	filesinkthread.h
 | 
			
		||||
 | 
			
		||||
FORMS += filesinkgui.ui
 | 
			
		||||
 | 
			
		||||
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
 | 
			
		||||
 | 
			
		||||
RESOURCES = ../../../sdrbase/resources/res.qrc
 | 
			
		||||
							
								
								
									
										421
									
								
								plugins/samplesink/sdrdaemonsink/filesinkgui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								plugins/samplesink/sdrdaemonsink/filesinkgui.ui
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,421 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<ui version="4.0">
 | 
			
		||||
 <class>FileSinkGui</class>
 | 
			
		||||
 <widget class="QWidget" name="FileSinkGui">
 | 
			
		||||
  <property name="geometry">
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>350</width>
 | 
			
		||||
    <height>190</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="sizePolicy">
 | 
			
		||||
   <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
 | 
			
		||||
    <horstretch>0</horstretch>
 | 
			
		||||
    <verstretch>0</verstretch>
 | 
			
		||||
   </sizepolicy>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="minimumSize">
 | 
			
		||||
   <size>
 | 
			
		||||
    <width>350</width>
 | 
			
		||||
    <height>190</height>
 | 
			
		||||
   </size>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="font">
 | 
			
		||||
   <font>
 | 
			
		||||
    <family>Sans Serif</family>
 | 
			
		||||
    <pointsize>9</pointsize>
 | 
			
		||||
   </font>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>FileSource</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_freq">
 | 
			
		||||
     <item>
 | 
			
		||||
      <layout class="QVBoxLayout" name="deviceUILayout">
 | 
			
		||||
       <item>
 | 
			
		||||
        <layout class="QHBoxLayout" name="deviceButtonsLayout">
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="ButtonSwitch" name="startStop">
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string>start/stop generation</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string/>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="icon">
 | 
			
		||||
            <iconset resource="../../../sdrbase/resources/res.qrc">
 | 
			
		||||
             <normaloff>:/play.png</normaloff>
 | 
			
		||||
             <normalon>:/stop.png</normalon>:/play.png</iconset>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <layout class="QHBoxLayout" name="deviceRateLayout">
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QLabel" name="deviceRateText">
 | 
			
		||||
           <property name="minimumSize">
 | 
			
		||||
            <size>
 | 
			
		||||
             <width>50</width>
 | 
			
		||||
             <height>0</height>
 | 
			
		||||
            </size>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string>I/Q sample rate kS/s</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>00000k</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="alignment">
 | 
			
		||||
            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <spacer name="freqLeftSpacer">
 | 
			
		||||
       <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="enabled">
 | 
			
		||||
        <bool>true</bool>
 | 
			
		||||
       </property>
 | 
			
		||||
       <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="cursor">
 | 
			
		||||
        <cursorShape>SizeVerCursor</cursorShape>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="focusPolicy">
 | 
			
		||||
        <enum>Qt::StrongFocus</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="toolTip">
 | 
			
		||||
        <string>Record center frequency in kHz</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QLabel" name="freqUnits">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string> kHz</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <spacer name="freqRightlSpacer">
 | 
			
		||||
       <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_freq">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Horizontal</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="fileSelectionLayout">
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QPushButton" name="showFileDialog">
 | 
			
		||||
       <property name="minimumSize">
 | 
			
		||||
        <size>
 | 
			
		||||
         <width>24</width>
 | 
			
		||||
         <height>24</height>
 | 
			
		||||
        </size>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="maximumSize">
 | 
			
		||||
        <size>
 | 
			
		||||
         <width>24</width>
 | 
			
		||||
         <height>24</height>
 | 
			
		||||
        </size>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="toolTip">
 | 
			
		||||
        <string>Open file</string>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string/>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="icon">
 | 
			
		||||
        <iconset resource="../../../sdrbase/resources/res.qrc">
 | 
			
		||||
         <normaloff>:/preset-load.png</normaloff>:/preset-load.png</iconset>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QLabel" name="fileNameText">
 | 
			
		||||
       <property name="enabled">
 | 
			
		||||
        <bool>false</bool>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="toolTip">
 | 
			
		||||
        <string>File currently opened</string>
 | 
			
		||||
       </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_rate">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Horizontal</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="rateControlLayout">
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QLabel" name="interpLabel">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Int</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QComboBox" name="interp">
 | 
			
		||||
       <property name="toolTip">
 | 
			
		||||
        <string>Interpolation</string>
 | 
			
		||||
       </property>
 | 
			
		||||
       <item>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>1</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>2</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>4</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>8</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>16</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>32</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>64</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </item>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QLabel" name="sampleRateLabel">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>SR</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="ValueDial" name="sampleRate" 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>DejaVu Sans Mono</family>
 | 
			
		||||
         <pointsize>12</pointsize>
 | 
			
		||||
        </font>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QLabel" name="sampleRateUnit">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>S/s</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <spacer name="horizontalSpacer_2">
 | 
			
		||||
       <property name="orientation">
 | 
			
		||||
        <enum>Qt::Horizontal</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="sizeHint" stdset="0">
 | 
			
		||||
        <size>
 | 
			
		||||
         <width>40</width>
 | 
			
		||||
         <height>20</height>
 | 
			
		||||
        </size>
 | 
			
		||||
       </property>
 | 
			
		||||
      </spacer>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QLabel" name="relTimeText">
 | 
			
		||||
       <property name="enabled">
 | 
			
		||||
        <bool>false</bool>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="minimumSize">
 | 
			
		||||
        <size>
 | 
			
		||||
         <width>90</width>
 | 
			
		||||
         <height>0</height>
 | 
			
		||||
        </size>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="toolTip">
 | 
			
		||||
        <string>Record time from start</string>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>00:00:00.000</string>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="alignment">
 | 
			
		||||
        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="Line" name="linePlay2">
 | 
			
		||||
       <property name="orientation">
 | 
			
		||||
        <enum>Qt::Vertical</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="padLayout">
 | 
			
		||||
     <item>
 | 
			
		||||
      <spacer name="verticaPadlSpacer">
 | 
			
		||||
       <property name="orientation">
 | 
			
		||||
        <enum>Qt::Vertical</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="sizeHint" stdset="0">
 | 
			
		||||
        <size>
 | 
			
		||||
         <width>20</width>
 | 
			
		||||
         <height>40</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>
 | 
			
		||||
  <customwidget>
 | 
			
		||||
   <class>ButtonSwitch</class>
 | 
			
		||||
   <extends>QToolButton</extends>
 | 
			
		||||
   <header>gui/buttonswitch.h</header>
 | 
			
		||||
  </customwidget>
 | 
			
		||||
 </customwidgets>
 | 
			
		||||
 <resources>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
  <include location="../../../sdrbase/resources/res.qrc"/>
 | 
			
		||||
 </resources>
 | 
			
		||||
 <connections/>
 | 
			
		||||
</ui>
 | 
			
		||||
							
								
								
									
										59
									
								
								plugins/samplesink/sdrdaemonsink/readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								plugins/samplesink/sdrdaemonsink/readme.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
			
		||||
<h1>File sink plugin</h1>
 | 
			
		||||
 | 
			
		||||
<h2>Introduction</h2>
 | 
			
		||||
 | 
			
		||||
This output sample sink plugin sends its samples to file in the SDRangel .sdriq format. 
 | 
			
		||||
 | 
			
		||||
The format is S16LE I/Q samples. Thus there are 4 bytes per sample. I and Q values are 16 bit signed integers. The file starts with a context header containing information about center frequency, sample rate and timestamp of the start of the recording. This header has a length which is a multiple of a sample size (normally 24 bytes thus 6 samples). Thus this file can be used as a raw I/Q file with S16LE samples tolerating a glitch at the start corresponding to the 6 "random" samples. For example in GNURadio you can simply specify your file source format as short complex.
 | 
			
		||||
 | 
			
		||||
You can also zap the 24 bytes header with this Linux command: `tail -c +25 myfile.sdriq > myfile.raw`
 | 
			
		||||
 | 
			
		||||
To convert in another format you may use the sox utility. For example to convert to 32 bit (float) complex samples do: `sox -r 48k −b 16 −e signed-integer -c 2 myfile.raw -e float -c 2 myfilec.raw`
 | 
			
		||||
 | 
			
		||||
Note that you have to specify the sampling rate and use .raw for the file extensions. 
 | 
			
		||||
 | 
			
		||||
<h2>Build</h2>
 | 
			
		||||
 | 
			
		||||
The plugin is always built.
 | 
			
		||||
 | 
			
		||||
<h2>Interface</h2>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
<h3>1: Start/Stop</h3>
 | 
			
		||||
 | 
			
		||||
Device start / stop button. 
 | 
			
		||||
 | 
			
		||||
  - Blue triangle icon: device is ready and can be started
 | 
			
		||||
  - Red square icon: device is running and can be stopped
 | 
			
		||||
  - Magenta (or pink) square icon: an error occured
 | 
			
		||||
  
 | 
			
		||||
<h3>2: File stream sample rate</h3>
 | 
			
		||||
 | 
			
		||||
This is the file stream sample rate in kS/s after interpolation (4) from the baseband stream. Thus this is the sample rate (7) multiplied by the interpolation factor (6). 
 | 
			
		||||
  
 | 
			
		||||
<h3>3: Frequency</h3>
 | 
			
		||||
 | 
			
		||||
This is the center frequency in kHz that will be put in the file header.
 | 
			
		||||
 | 
			
		||||
<h3>4: Output file selection</h3>
 | 
			
		||||
 | 
			
		||||
Use this file dialog to specify the output file.
 | 
			
		||||
 | 
			
		||||
<h3>5: File name</h3>
 | 
			
		||||
 | 
			
		||||
This is the file path of the output file.
 | 
			
		||||
 | 
			
		||||
<h3>6: Interpolation factor</h3>
 | 
			
		||||
 | 
			
		||||
The baseband stream is interpolated by this value before being written to file. It can vary in powers of two from 1 (no interpolation) to 64.
 | 
			
		||||
 | 
			
		||||
<h3>7: Baseband sample rate</h3>
 | 
			
		||||
 | 
			
		||||
This is the baseband sample rate before interpolation in S/s.
 | 
			
		||||
 | 
			
		||||
Use the wheels to adjust the sample rate. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position.   
 | 
			
		||||
 | 
			
		||||
<h3>8: Time counter</h3>
 | 
			
		||||
 | 
			
		||||
This is the recording time count in HH:MM:SS.SSS
 | 
			
		||||
							
								
								
									
										337
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										337
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,337 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2016 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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 <QDebug>
 | 
			
		||||
 | 
			
		||||
#include <QTime>
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QFileDialog>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
#include "ui_filesinkgui.h"
 | 
			
		||||
#include "plugin/pluginapi.h"
 | 
			
		||||
#include "gui/colormapper.h"
 | 
			
		||||
#include "gui/glspectrum.h"
 | 
			
		||||
#include "dsp/dspengine.h"
 | 
			
		||||
#include "dsp/dspcommands.h"
 | 
			
		||||
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
 | 
			
		||||
#include "device/devicesinkapi.h"
 | 
			
		||||
#include "sdrdaemonsinkgui.h"
 | 
			
		||||
 | 
			
		||||
FileSinkGui::FileSinkGui(DeviceSinkAPI *deviceAPI, QWidget* parent) :
 | 
			
		||||
	QWidget(parent),
 | 
			
		||||
	ui(new Ui::FileSinkGui),
 | 
			
		||||
	m_deviceAPI(deviceAPI),
 | 
			
		||||
	m_settings(),
 | 
			
		||||
	m_deviceSampleSink(0),
 | 
			
		||||
	m_sampleRate(0),
 | 
			
		||||
	m_generation(false),
 | 
			
		||||
	m_fileName("./test.sdriq"),
 | 
			
		||||
	m_startingTimeStamp(0),
 | 
			
		||||
	m_samplesCount(0),
 | 
			
		||||
	m_tickCount(0),
 | 
			
		||||
	m_lastEngineState((DSPDeviceSinkEngine::State)-1)
 | 
			
		||||
{
 | 
			
		||||
	ui->setupUi(this);
 | 
			
		||||
 | 
			
		||||
	ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
 | 
			
		||||
	ui->centerFrequency->setValueRange(7, 0, pow(10,7));
 | 
			
		||||
 | 
			
		||||
    ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::ReverseGreenYellow));
 | 
			
		||||
    ui->sampleRate->setValueRange(7, 32000U, 9000000U);
 | 
			
		||||
 | 
			
		||||
	ui->fileNameText->setText(m_fileName);
 | 
			
		||||
 | 
			
		||||
	connect(&(m_deviceAPI->getMainWindow()->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick()));
 | 
			
		||||
	connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
 | 
			
		||||
	connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
 | 
			
		||||
	m_statusTimer.start(500);
 | 
			
		||||
 | 
			
		||||
	displaySettings();
 | 
			
		||||
 | 
			
		||||
	m_deviceSampleSink = new FileSinkOutput(m_deviceAPI, m_deviceAPI->getMainWindow()->getMasterTimer());
 | 
			
		||||
    connect(m_deviceSampleSink->getOutputMessageQueueToGUI(), SIGNAL(messageEnqueued()), this, SLOT(handleSinkMessages()));
 | 
			
		||||
	m_deviceAPI->setSink(m_deviceSampleSink);
 | 
			
		||||
 | 
			
		||||
    connect(m_deviceAPI->getDeviceOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleDSPMessages()), Qt::QueuedConnection);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileSinkGui::~FileSinkGui()
 | 
			
		||||
{
 | 
			
		||||
	delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::destroy()
 | 
			
		||||
{
 | 
			
		||||
	delete this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::setName(const QString& name)
 | 
			
		||||
{
 | 
			
		||||
	setObjectName(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString FileSinkGui::getName() const
 | 
			
		||||
{
 | 
			
		||||
	return objectName();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::resetToDefaults()
 | 
			
		||||
{
 | 
			
		||||
	m_settings.resetToDefaults();
 | 
			
		||||
	displaySettings();
 | 
			
		||||
	sendSettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qint64 FileSinkGui::getCenterFrequency() const
 | 
			
		||||
{
 | 
			
		||||
	return m_settings.m_centerFrequency;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::setCenterFrequency(qint64 centerFrequency)
 | 
			
		||||
{
 | 
			
		||||
    m_settings.m_centerFrequency = centerFrequency;
 | 
			
		||||
	displaySettings();
 | 
			
		||||
	sendSettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QByteArray FileSinkGui::serialize() const
 | 
			
		||||
{
 | 
			
		||||
	return m_settings.serialize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FileSinkGui::deserialize(const QByteArray& data)
 | 
			
		||||
{
 | 
			
		||||
	if(m_settings.deserialize(data)) {
 | 
			
		||||
		displaySettings();
 | 
			
		||||
		sendSettings();
 | 
			
		||||
		return true;
 | 
			
		||||
	} else {
 | 
			
		||||
		resetToDefaults();
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FileSinkGui::handleMessage(const Message& message)
 | 
			
		||||
{
 | 
			
		||||
	if (FileSinkOutput::MsgReportFileSinkGeneration::match(message))
 | 
			
		||||
	{
 | 
			
		||||
		m_generation = ((FileSinkOutput::MsgReportFileSinkGeneration&)message).getAcquisition();
 | 
			
		||||
		updateWithGeneration();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else if (FileSinkOutput::MsgReportFileSinkStreamTiming::match(message))
 | 
			
		||||
	{
 | 
			
		||||
		m_samplesCount = ((FileSinkOutput::MsgReportFileSinkStreamTiming&)message).getSamplesCount();
 | 
			
		||||
		updateWithStreamTime();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::handleDSPMessages()
 | 
			
		||||
{
 | 
			
		||||
    Message* message;
 | 
			
		||||
 | 
			
		||||
    while ((message = m_deviceAPI->getDeviceOutputMessageQueue()->pop()) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        qDebug("FileSinkGui::handleDSPMessages: message: %s", message->getIdentifier());
 | 
			
		||||
 | 
			
		||||
        if (DSPSignalNotification::match(*message))
 | 
			
		||||
        {
 | 
			
		||||
            DSPSignalNotification* notif = (DSPSignalNotification*) message;
 | 
			
		||||
            qDebug("FileSinkGui::handleDSPMessages: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
 | 
			
		||||
            m_sampleRate = notif->getSampleRate();
 | 
			
		||||
            m_deviceCenterFrequency = notif->getCenterFrequency();
 | 
			
		||||
            updateSampleRateAndFrequency();
 | 
			
		||||
 | 
			
		||||
            delete message;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::handleSinkMessages()
 | 
			
		||||
{
 | 
			
		||||
    Message* message;
 | 
			
		||||
 | 
			
		||||
    while ((message = m_deviceSampleSink->getOutputMessageQueueToGUI()->pop()) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        //qDebug("FileSourceGui::handleSourceMessages: message: %s", message->getIdentifier());
 | 
			
		||||
 | 
			
		||||
        if (handleMessage(*message))
 | 
			
		||||
        {
 | 
			
		||||
            delete message;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::updateSampleRateAndFrequency()
 | 
			
		||||
{
 | 
			
		||||
    m_deviceAPI->getSpectrum()->setSampleRate(m_sampleRate);
 | 
			
		||||
    m_deviceAPI->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency);
 | 
			
		||||
    ui->deviceRateText->setText(tr("%1k").arg((float)(m_sampleRate*(1<<m_settings.m_log2Interp)) / 1000));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::displaySettings()
 | 
			
		||||
{
 | 
			
		||||
    ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
 | 
			
		||||
    ui->sampleRate->setValue(m_settings.m_sampleRate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::sendSettings()
 | 
			
		||||
{
 | 
			
		||||
    if(!m_updateTimer.isActive())
 | 
			
		||||
        m_updateTimer.start(100);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::updateHardware()
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "FileSinkGui::updateHardware";
 | 
			
		||||
    FileSinkOutput::MsgConfigureFileSink* message = FileSinkOutput::MsgConfigureFileSink::create(m_settings);
 | 
			
		||||
    m_deviceSampleSink->getInputMessageQueue()->push(message);
 | 
			
		||||
    m_updateTimer.stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::updateStatus()
 | 
			
		||||
{
 | 
			
		||||
    int state = m_deviceAPI->state();
 | 
			
		||||
 | 
			
		||||
    if(m_lastEngineState != state)
 | 
			
		||||
    {
 | 
			
		||||
        switch(state)
 | 
			
		||||
        {
 | 
			
		||||
            case DSPDeviceSinkEngine::StNotStarted:
 | 
			
		||||
                ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
 | 
			
		||||
                break;
 | 
			
		||||
            case DSPDeviceSinkEngine::StIdle:
 | 
			
		||||
                ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
 | 
			
		||||
                break;
 | 
			
		||||
            case DSPDeviceSinkEngine::StRunning:
 | 
			
		||||
                ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
 | 
			
		||||
                break;
 | 
			
		||||
            case DSPDeviceSinkEngine::StError:
 | 
			
		||||
                ui->startStop->setStyleSheet("QToolButton { background-color : magenta; }");
 | 
			
		||||
                QMessageBox::information(this, tr("Message"), m_deviceAPI->errorMessage());
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_lastEngineState = state;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::on_centerFrequency_changed(quint64 value)
 | 
			
		||||
{
 | 
			
		||||
    m_settings.m_centerFrequency = value * 1000;
 | 
			
		||||
    sendSettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::on_sampleRate_changed(quint64 value)
 | 
			
		||||
{
 | 
			
		||||
    m_settings.m_sampleRate = value;
 | 
			
		||||
    sendSettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::on_interp_currentIndexChanged(int index)
 | 
			
		||||
{
 | 
			
		||||
    if (index < 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_settings.m_log2Interp = index;
 | 
			
		||||
    updateSampleRateAndFrequency();
 | 
			
		||||
    sendSettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::on_startStop_toggled(bool checked)
 | 
			
		||||
{
 | 
			
		||||
    if (checked)
 | 
			
		||||
    {
 | 
			
		||||
        if (m_deviceAPI->initGeneration())
 | 
			
		||||
        {
 | 
			
		||||
            if (!m_deviceAPI->startGeneration())
 | 
			
		||||
            {
 | 
			
		||||
                qDebug("FileSinkGui::on_startStop_toggled: device start failed");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            DSPEngine::instance()->startAudioInput();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_deviceAPI->stopGeneration();
 | 
			
		||||
        DSPEngine::instance()->stopAudioInput();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::on_showFileDialog_clicked(bool checked)
 | 
			
		||||
{
 | 
			
		||||
    QString fileName = QFileDialog::getSaveFileName(this,
 | 
			
		||||
        tr("Save I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)"));
 | 
			
		||||
 | 
			
		||||
	if (fileName != "")
 | 
			
		||||
	{
 | 
			
		||||
		m_fileName = fileName;
 | 
			
		||||
		ui->fileNameText->setText(m_fileName);
 | 
			
		||||
		configureFileName();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::configureFileName()
 | 
			
		||||
{
 | 
			
		||||
	qDebug() << "FileSinkGui::configureFileName: " << m_fileName.toStdString().c_str();
 | 
			
		||||
	FileSinkOutput::MsgConfigureFileSinkName* message = FileSinkOutput::MsgConfigureFileSinkName::create(m_fileName);
 | 
			
		||||
	m_deviceSampleSink->getInputMessageQueue()->push(message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::updateWithGeneration()
 | 
			
		||||
{
 | 
			
		||||
	ui->showFileDialog->setEnabled(!m_generation);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::updateWithStreamTime()
 | 
			
		||||
{
 | 
			
		||||
	int t_sec = 0;
 | 
			
		||||
	int t_msec = 0;
 | 
			
		||||
 | 
			
		||||
	if (m_settings.m_sampleRate > 0){
 | 
			
		||||
		t_msec = ((m_samplesCount * 1000) / m_settings.m_sampleRate) % 1000;
 | 
			
		||||
		t_sec = m_samplesCount / m_settings.m_sampleRate;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	QTime t(0, 0, 0, 0);
 | 
			
		||||
	t = t.addSecs(t_sec);
 | 
			
		||||
	t = t.addMSecs(t_msec);
 | 
			
		||||
	QString s_timems = t.toString("hh:mm:ss.zzz");
 | 
			
		||||
	ui->relTimeText->setText(s_timems);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkGui::tick()
 | 
			
		||||
{
 | 
			
		||||
	if ((++m_tickCount & 0xf) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		FileSinkOutput::MsgConfigureFileSinkStreamTiming* message = FileSinkOutput::MsgConfigureFileSinkStreamTiming::create();
 | 
			
		||||
		m_deviceSampleSink->getInputMessageQueue()->push(message);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										90
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2016 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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_FILESINKGUI_H
 | 
			
		||||
#define INCLUDE_FILESINKGUI_H
 | 
			
		||||
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
 | 
			
		||||
#include "plugin/plugingui.h"
 | 
			
		||||
#include "../sdrdaemonoutput/filesinksettings.h"
 | 
			
		||||
#include "sdrdaemonsinkoutput.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DeviceSinkAPI;
 | 
			
		||||
class DeviceSampleSink;
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
	class FileSinkGui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FileSinkGui : public QWidget, public PluginGUI {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	explicit FileSinkGui(DeviceSinkAPI *deviceAPI, QWidget* parent = NULL);
 | 
			
		||||
	virtual ~FileSinkGui();
 | 
			
		||||
	void destroy();
 | 
			
		||||
 | 
			
		||||
	void setName(const QString& name);
 | 
			
		||||
	QString getName() const;
 | 
			
		||||
 | 
			
		||||
	void resetToDefaults();
 | 
			
		||||
	virtual qint64 getCenterFrequency() const;
 | 
			
		||||
	virtual void setCenterFrequency(qint64 centerFrequency);
 | 
			
		||||
	QByteArray serialize() const;
 | 
			
		||||
	bool deserialize(const QByteArray& data);
 | 
			
		||||
	virtual bool handleMessage(const Message& message);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Ui::FileSinkGui* ui;
 | 
			
		||||
 | 
			
		||||
	DeviceSinkAPI* m_deviceAPI;
 | 
			
		||||
	FileSinkSettings m_settings;
 | 
			
		||||
    QString m_fileName;
 | 
			
		||||
	QTimer m_updateTimer;
 | 
			
		||||
    QTimer m_statusTimer;
 | 
			
		||||
	DeviceSampleSink* m_deviceSampleSink;
 | 
			
		||||
    int m_sampleRate;
 | 
			
		||||
    quint64 m_deviceCenterFrequency; //!< Center frequency in device
 | 
			
		||||
    bool m_generation;
 | 
			
		||||
	std::time_t m_startingTimeStamp;
 | 
			
		||||
	int m_samplesCount;
 | 
			
		||||
	std::size_t m_tickCount;
 | 
			
		||||
	int m_lastEngineState;
 | 
			
		||||
 | 
			
		||||
	void displaySettings();
 | 
			
		||||
	void displayTime();
 | 
			
		||||
	void sendSettings();
 | 
			
		||||
	void configureFileName();
 | 
			
		||||
	void updateWithGeneration();
 | 
			
		||||
	void updateWithStreamTime();
 | 
			
		||||
	void updateSampleRateAndFrequency();
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void handleDSPMessages();
 | 
			
		||||
    void handleSinkMessages();
 | 
			
		||||
    void on_centerFrequency_changed(quint64 value);
 | 
			
		||||
    void on_sampleRate_changed(quint64 value);
 | 
			
		||||
	void on_startStop_toggled(bool checked);
 | 
			
		||||
	void on_showFileDialog_clicked(bool checked);
 | 
			
		||||
	void on_interp_currentIndexChanged(int index);
 | 
			
		||||
    void updateHardware();
 | 
			
		||||
    void updateStatus();
 | 
			
		||||
	void tick();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDE_FILESINKGUI_H
 | 
			
		||||
							
								
								
									
										240
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,240 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2016 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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 <QDebug>
 | 
			
		||||
 | 
			
		||||
#include "util/simpleserializer.h"
 | 
			
		||||
#include "dsp/dspcommands.h"
 | 
			
		||||
#include "dsp/dspengine.h"
 | 
			
		||||
#include "dsp/filerecord.h"
 | 
			
		||||
 | 
			
		||||
#include "device/devicesinkapi.h"
 | 
			
		||||
 | 
			
		||||
#include "sdrdaemonsinkgui.h"
 | 
			
		||||
#include "sdrdaemonsinkoutput.h"
 | 
			
		||||
#include "sdrdaemonsinkthread.h"
 | 
			
		||||
 | 
			
		||||
MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgConfigureFileSink, Message)
 | 
			
		||||
MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgConfigureFileSinkName, Message)
 | 
			
		||||
MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgConfigureFileSinkWork, Message)
 | 
			
		||||
MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgConfigureFileSinkStreamTiming, Message)
 | 
			
		||||
MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgReportFileSinkGeneration, Message)
 | 
			
		||||
MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgReportFileSinkStreamTiming, Message)
 | 
			
		||||
 | 
			
		||||
FileSinkOutput::FileSinkOutput(DeviceSinkAPI *deviceAPI, const QTimer& masterTimer) :
 | 
			
		||||
    m_deviceAPI(deviceAPI),
 | 
			
		||||
	m_settings(),
 | 
			
		||||
	m_fileSinkThread(0),
 | 
			
		||||
	m_deviceDescription("FileSink"),
 | 
			
		||||
	m_fileName("./test.sdriq"),
 | 
			
		||||
	m_startingTimeStamp(0),
 | 
			
		||||
	m_masterTimer(masterTimer)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileSinkOutput::~FileSinkOutput()
 | 
			
		||||
{
 | 
			
		||||
	stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkOutput::openFileStream()
 | 
			
		||||
{
 | 
			
		||||
	if (m_ofstream.is_open()) {
 | 
			
		||||
		m_ofstream.close();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_ofstream.open(m_fileName.toStdString().c_str(), std::ios::binary);
 | 
			
		||||
 | 
			
		||||
	int actualSampleRate = m_settings.m_sampleRate * (1<<m_settings.m_log2Interp);
 | 
			
		||||
	m_ofstream.write((const char *) &actualSampleRate, sizeof(int));
 | 
			
		||||
    //m_ofstream.write((const char *) &m_settings.m_sampleRate, sizeof(int));
 | 
			
		||||
	m_ofstream.write((const char *) &m_settings.m_centerFrequency, sizeof(quint64));
 | 
			
		||||
    m_startingTimeStamp = time(0);
 | 
			
		||||
    m_ofstream.write((const char *) &m_startingTimeStamp, sizeof(std::time_t));
 | 
			
		||||
 | 
			
		||||
	qDebug() << "FileSinkOutput::openFileStream: " << m_fileName.toStdString().c_str();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FileSinkOutput::start()
 | 
			
		||||
{
 | 
			
		||||
	QMutexLocker mutexLocker(&m_mutex);
 | 
			
		||||
	qDebug() << "FileSinkOutput::start";
 | 
			
		||||
 | 
			
		||||
	openFileStream();
 | 
			
		||||
 | 
			
		||||
	if((m_fileSinkThread = new FileSinkThread(&m_ofstream, &m_sampleSourceFifo)) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		qFatal("out of memory");
 | 
			
		||||
		stop();
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
 | 
			
		||||
	m_fileSinkThread->setLog2Interpolation(m_settings.m_log2Interp);
 | 
			
		||||
	m_fileSinkThread->connectTimer(m_masterTimer);
 | 
			
		||||
	m_fileSinkThread->startWork();
 | 
			
		||||
 | 
			
		||||
	mutexLocker.unlock();
 | 
			
		||||
	//applySettings(m_generalSettings, m_settings, true);
 | 
			
		||||
	qDebug("FileSinkOutput::start: started");
 | 
			
		||||
 | 
			
		||||
	MsgReportFileSinkGeneration *report = MsgReportFileSinkGeneration::create(true); // acquisition on
 | 
			
		||||
	getOutputMessageQueueToGUI()->push(report);
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkOutput::stop()
 | 
			
		||||
{
 | 
			
		||||
	qDebug() << "FileSourceInput::stop";
 | 
			
		||||
	QMutexLocker mutexLocker(&m_mutex);
 | 
			
		||||
 | 
			
		||||
	if(m_fileSinkThread != 0)
 | 
			
		||||
	{
 | 
			
		||||
		m_fileSinkThread->stopWork();
 | 
			
		||||
		delete m_fileSinkThread;
 | 
			
		||||
		m_fileSinkThread = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    if (m_ofstream.is_open()) {
 | 
			
		||||
        m_ofstream.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MsgReportFileSinkGeneration *report = MsgReportFileSinkGeneration::create(false); // acquisition off
 | 
			
		||||
	getOutputMessageQueueToGUI()->push(report);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QString& FileSinkOutput::getDeviceDescription() const
 | 
			
		||||
{
 | 
			
		||||
	return m_deviceDescription;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FileSinkOutput::getSampleRate() const
 | 
			
		||||
{
 | 
			
		||||
	return m_settings.m_sampleRate;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint64 FileSinkOutput::getCenterFrequency() const
 | 
			
		||||
{
 | 
			
		||||
	return m_settings.m_centerFrequency;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::time_t FileSinkOutput::getStartingTimeStamp() const
 | 
			
		||||
{
 | 
			
		||||
	return m_startingTimeStamp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FileSinkOutput::handleMessage(const Message& message)
 | 
			
		||||
{
 | 
			
		||||
	if (MsgConfigureFileSinkName::match(message))
 | 
			
		||||
	{
 | 
			
		||||
		MsgConfigureFileSinkName& conf = (MsgConfigureFileSinkName&) message;
 | 
			
		||||
		m_fileName = conf.getFileName();
 | 
			
		||||
		openFileStream();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else if (MsgConfigureFileSink::match(message))
 | 
			
		||||
    {
 | 
			
		||||
	    qDebug() << "FileSinkOutput::handleMessage: MsgConfigureFileSink";
 | 
			
		||||
	    MsgConfigureFileSink& conf = (MsgConfigureFileSink&) message;
 | 
			
		||||
        applySettings(conf.getSettings(), false);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
	else if (MsgConfigureFileSinkWork::match(message))
 | 
			
		||||
	{
 | 
			
		||||
		MsgConfigureFileSinkWork& conf = (MsgConfigureFileSinkWork&) message;
 | 
			
		||||
		bool working = conf.isWorking();
 | 
			
		||||
 | 
			
		||||
		if (m_fileSinkThread != 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (working)
 | 
			
		||||
			{
 | 
			
		||||
				m_fileSinkThread->startWork();
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				m_fileSinkThread->stopWork();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else if (MsgConfigureFileSinkStreamTiming::match(message))
 | 
			
		||||
	{
 | 
			
		||||
        MsgReportFileSinkStreamTiming *report;
 | 
			
		||||
 | 
			
		||||
		if (m_fileSinkThread != 0)
 | 
			
		||||
		{
 | 
			
		||||
			report = MsgReportFileSinkStreamTiming::create(m_fileSinkThread->getSamplesCount());
 | 
			
		||||
			getOutputMessageQueueToGUI()->push(report);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkOutput::applySettings(const FileSinkSettings& settings, bool force)
 | 
			
		||||
{
 | 
			
		||||
    QMutexLocker mutexLocker(&m_mutex);
 | 
			
		||||
    bool forwardChange = false;
 | 
			
		||||
 | 
			
		||||
    if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency))
 | 
			
		||||
    {
 | 
			
		||||
        m_settings.m_centerFrequency = settings.m_centerFrequency;
 | 
			
		||||
        forwardChange = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (force || (m_settings.m_sampleRate != settings.m_sampleRate))
 | 
			
		||||
    {
 | 
			
		||||
        m_settings.m_sampleRate = settings.m_sampleRate;
 | 
			
		||||
 | 
			
		||||
        if (m_fileSinkThread != 0)
 | 
			
		||||
        {
 | 
			
		||||
            m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        forwardChange = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (force || (m_settings.m_log2Interp != settings.m_log2Interp))
 | 
			
		||||
    {
 | 
			
		||||
        m_settings.m_log2Interp = settings.m_log2Interp;
 | 
			
		||||
 | 
			
		||||
        if (m_fileSinkThread != 0)
 | 
			
		||||
        {
 | 
			
		||||
            m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        forwardChange = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (forwardChange)
 | 
			
		||||
    {
 | 
			
		||||
        qDebug("FileSinkOutput::applySettings: forward: m_centerFrequency: %llu m_sampleRate: %llu m_log2Interp: %d",
 | 
			
		||||
                m_settings.m_centerFrequency,
 | 
			
		||||
                m_settings.m_sampleRate,
 | 
			
		||||
                m_settings.m_log2Interp);
 | 
			
		||||
        DSPSignalNotification *notif = new DSPSignalNotification(m_settings.m_sampleRate, m_settings.m_centerFrequency);
 | 
			
		||||
        m_deviceAPI->getDeviceInputMessageQueue()->push(notif);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										180
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,180 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2016 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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_FILESINKOUTPUT_H
 | 
			
		||||
#define INCLUDE_FILESINKOUTPUT_H
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
 | 
			
		||||
#include "dsp/devicesamplesink.h"
 | 
			
		||||
 | 
			
		||||
#include "sdrdaemonsinksettings.h"
 | 
			
		||||
 | 
			
		||||
class FileSinkThread;
 | 
			
		||||
class DeviceSinkAPI;
 | 
			
		||||
 | 
			
		||||
class FileSinkOutput : public DeviceSampleSink {
 | 
			
		||||
public:
 | 
			
		||||
	class MsgConfigureFileSink : public Message {
 | 
			
		||||
		MESSAGE_CLASS_DECLARATION
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		const FileSinkSettings& getSettings() const { return m_settings; }
 | 
			
		||||
 | 
			
		||||
		static MsgConfigureFileSink* create(const FileSinkSettings& settings)
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgConfigureFileSink(settings);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		FileSinkSettings m_settings;
 | 
			
		||||
 | 
			
		||||
		MsgConfigureFileSink(const FileSinkSettings& settings) :
 | 
			
		||||
			Message(),
 | 
			
		||||
			m_settings(settings)
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class MsgConfigureFileSinkName : public Message {
 | 
			
		||||
		MESSAGE_CLASS_DECLARATION
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		const QString& getFileName() const { return m_fileName; }
 | 
			
		||||
 | 
			
		||||
		static MsgConfigureFileSinkName* create(const QString& fileName)
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgConfigureFileSinkName(fileName);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		QString m_fileName;
 | 
			
		||||
 | 
			
		||||
		MsgConfigureFileSinkName(const QString& fileName) :
 | 
			
		||||
			Message(),
 | 
			
		||||
			m_fileName(fileName)
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class MsgConfigureFileSinkWork : public Message {
 | 
			
		||||
		MESSAGE_CLASS_DECLARATION
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		bool isWorking() const { return m_working; }
 | 
			
		||||
 | 
			
		||||
		static MsgConfigureFileSinkWork* create(bool working)
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgConfigureFileSinkWork(working);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		bool m_working;
 | 
			
		||||
 | 
			
		||||
		MsgConfigureFileSinkWork(bool working) :
 | 
			
		||||
			Message(),
 | 
			
		||||
			m_working(working)
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class MsgConfigureFileSinkStreamTiming : public Message {
 | 
			
		||||
		MESSAGE_CLASS_DECLARATION
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
 | 
			
		||||
		static MsgConfigureFileSinkStreamTiming* create()
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgConfigureFileSinkStreamTiming();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
 | 
			
		||||
		MsgConfigureFileSinkStreamTiming() :
 | 
			
		||||
			Message()
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class MsgReportFileSinkGeneration : public Message {
 | 
			
		||||
		MESSAGE_CLASS_DECLARATION
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		bool getAcquisition() const { return m_acquisition; }
 | 
			
		||||
 | 
			
		||||
		static MsgReportFileSinkGeneration* create(bool acquisition)
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgReportFileSinkGeneration(acquisition);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	protected:
 | 
			
		||||
		bool m_acquisition;
 | 
			
		||||
 | 
			
		||||
		MsgReportFileSinkGeneration(bool acquisition) :
 | 
			
		||||
			Message(),
 | 
			
		||||
			m_acquisition(acquisition)
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class MsgReportFileSinkStreamTiming : public Message {
 | 
			
		||||
		MESSAGE_CLASS_DECLARATION
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		std::size_t getSamplesCount() const { return m_samplesCount; }
 | 
			
		||||
 | 
			
		||||
		static MsgReportFileSinkStreamTiming* create(std::size_t samplesCount)
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgReportFileSinkStreamTiming(samplesCount);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	protected:
 | 
			
		||||
		std::size_t m_samplesCount;
 | 
			
		||||
 | 
			
		||||
		MsgReportFileSinkStreamTiming(std::size_t samplesCount) :
 | 
			
		||||
			Message(),
 | 
			
		||||
			m_samplesCount(samplesCount)
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	FileSinkOutput(DeviceSinkAPI *deviceAPI, const QTimer& masterTimer);
 | 
			
		||||
	virtual ~FileSinkOutput();
 | 
			
		||||
 | 
			
		||||
	virtual bool start();
 | 
			
		||||
	virtual void stop();
 | 
			
		||||
 | 
			
		||||
	virtual const QString& getDeviceDescription() const;
 | 
			
		||||
	virtual int getSampleRate() const;
 | 
			
		||||
	virtual quint64 getCenterFrequency() const;
 | 
			
		||||
	std::time_t getStartingTimeStamp() const;
 | 
			
		||||
 | 
			
		||||
	virtual bool handleMessage(const Message& message);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    DeviceSinkAPI *m_deviceAPI;
 | 
			
		||||
	QMutex m_mutex;
 | 
			
		||||
	FileSinkSettings m_settings;
 | 
			
		||||
	std::ofstream m_ofstream;
 | 
			
		||||
	FileSinkThread* m_fileSinkThread;
 | 
			
		||||
	QString m_deviceDescription;
 | 
			
		||||
	QString m_fileName;
 | 
			
		||||
	std::time_t m_startingTimeStamp;
 | 
			
		||||
	const QTimer& m_masterTimer;
 | 
			
		||||
 | 
			
		||||
	void openFileStream();
 | 
			
		||||
	void applySettings(const FileSinkSettings& settings, bool force = false);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDE_FILESINKOUTPUT_H
 | 
			
		||||
							
								
								
									
										85
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2016 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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 <QtPlugin>
 | 
			
		||||
#include <QAction>
 | 
			
		||||
#include "plugin/pluginapi.h"
 | 
			
		||||
#include "util/simpleserializer.h"
 | 
			
		||||
 | 
			
		||||
#include "device/devicesinkapi.h"
 | 
			
		||||
 | 
			
		||||
#include "sdrdaemonsinkgui.h"
 | 
			
		||||
#include "sdrdaemonsinkplugin.h"
 | 
			
		||||
 | 
			
		||||
const PluginDescriptor FileSinkPlugin::m_pluginDescriptor = {
 | 
			
		||||
	QString("File sink output"),
 | 
			
		||||
	QString("3.4.0"),
 | 
			
		||||
	QString("(c) Edouard Griffiths, F4EXB"),
 | 
			
		||||
	QString("https://github.com/f4exb/sdrangel"),
 | 
			
		||||
	true,
 | 
			
		||||
	QString("https://github.com/f4exb/sdrangel")
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const QString FileSinkPlugin::m_hardwareID = "FileSink";
 | 
			
		||||
const QString FileSinkPlugin::m_deviceTypeID = FILESINK_DEVICE_TYPE_ID;
 | 
			
		||||
 | 
			
		||||
FileSinkPlugin::FileSinkPlugin(QObject* parent) :
 | 
			
		||||
	QObject(parent)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const PluginDescriptor& FileSinkPlugin::getPluginDescriptor() const
 | 
			
		||||
{
 | 
			
		||||
	return m_pluginDescriptor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSinkPlugin::initPlugin(PluginAPI* pluginAPI)
 | 
			
		||||
{
 | 
			
		||||
	pluginAPI->registerSampleSink(m_deviceTypeID, this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PluginInterface::SamplingDevices FileSinkPlugin::enumSampleSinks()
 | 
			
		||||
{
 | 
			
		||||
	SamplingDevices result;
 | 
			
		||||
	int count = 1;
 | 
			
		||||
 | 
			
		||||
	for(int i = 0; i < count; i++)
 | 
			
		||||
	{
 | 
			
		||||
		QString displayedName(QString("FileSink[%1]").arg(i));
 | 
			
		||||
 | 
			
		||||
		result.append(SamplingDevice(displayedName,
 | 
			
		||||
		        m_hardwareID,
 | 
			
		||||
				m_deviceTypeID,
 | 
			
		||||
				QString::null,
 | 
			
		||||
				i));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PluginGUI* FileSinkPlugin::createSampleSinkPluginGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI)
 | 
			
		||||
{
 | 
			
		||||
	if(sinkId == m_deviceTypeID)
 | 
			
		||||
	{
 | 
			
		||||
		FileSinkGui* gui = new FileSinkGui(deviceAPI);
 | 
			
		||||
		*widget = gui;
 | 
			
		||||
		return gui;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkplugin.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2016 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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_FILESINKPLUGIN_H
 | 
			
		||||
#define INCLUDE_FILESINKPLUGIN_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include "plugin/plugininterface.h"
 | 
			
		||||
 | 
			
		||||
#define FILESINK_DEVICE_TYPE_ID "sdrangel.samplesink.filesink"
 | 
			
		||||
 | 
			
		||||
class PluginAPI;
 | 
			
		||||
class DeviceSinkAPI;
 | 
			
		||||
 | 
			
		||||
class FileSinkPlugin : public QObject, public PluginInterface {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
	Q_INTERFACES(PluginInterface)
 | 
			
		||||
	Q_PLUGIN_METADATA(IID FILESINK_DEVICE_TYPE_ID)
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	explicit FileSinkPlugin(QObject* parent = NULL);
 | 
			
		||||
 | 
			
		||||
	const PluginDescriptor& getPluginDescriptor() const;
 | 
			
		||||
	void initPlugin(PluginAPI* pluginAPI);
 | 
			
		||||
 | 
			
		||||
	virtual SamplingDevices enumSampleSinks();
 | 
			
		||||
	virtual PluginGUI* createSampleSinkPluginGUI(const QString& sinkId, QWidget **widget, DeviceSinkAPI *deviceAPI);
 | 
			
		||||
 | 
			
		||||
	static const QString m_hardwareID;
 | 
			
		||||
    static const QString m_deviceTypeID;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	static const PluginDescriptor m_pluginDescriptor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDE_FILESOURCEPLUGIN_H
 | 
			
		||||
							
								
								
									
										72
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinksettings.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinksettings.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2017 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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 "util/simpleserializer.h"
 | 
			
		||||
#include "sdrdaemonsinksettings.h"
 | 
			
		||||
 | 
			
		||||
SDRdaemonSinkSettings::SDRdaemonSinkSettings()
 | 
			
		||||
{
 | 
			
		||||
    resetToDefaults();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkSettings::resetToDefaults()
 | 
			
		||||
{
 | 
			
		||||
    m_centerFrequency = 435000*1000;
 | 
			
		||||
    m_sampleRate = 48000;
 | 
			
		||||
    m_log2Interp = 0;
 | 
			
		||||
    m_address = "127.0.0.1";
 | 
			
		||||
    m_port = 9090;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QByteArray SDRdaemonSinkSettings::serialize() const
 | 
			
		||||
{
 | 
			
		||||
    SimpleSerializer s(1);
 | 
			
		||||
 | 
			
		||||
    s.writeU64(1, m_sampleRate);
 | 
			
		||||
    s.writeU32(2, m_log2Interp);
 | 
			
		||||
    s.writeString(3, m_address);
 | 
			
		||||
    s.writeU32(4, m_port);
 | 
			
		||||
 | 
			
		||||
    return s.final();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SDRdaemonSinkSettings::deserialize(const QByteArray& data)
 | 
			
		||||
{
 | 
			
		||||
    SimpleDeserializer d(data);
 | 
			
		||||
 | 
			
		||||
    if (!d.isValid())
 | 
			
		||||
    {
 | 
			
		||||
        resetToDefaults();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (d.getVersion() == 1)
 | 
			
		||||
    {
 | 
			
		||||
        int intval;
 | 
			
		||||
        quint32 uintval;
 | 
			
		||||
        d.readU64(1, &m_sampleRate, 48000);
 | 
			
		||||
        d.readU32(2, &m_log2Interp, 0);
 | 
			
		||||
        d.readString(3, &m_address, "");
 | 
			
		||||
        d.readU32(4, &uintval, 9090);
 | 
			
		||||
        m_port = uintval % (1<<16);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        resetToDefaults();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinksettings.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinksettings.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2017 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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 PLUGINS_SAMPLESINK_SDRDAEMONSINK_SDRDAEMONSINKSETTINGS_H_
 | 
			
		||||
#define PLUGINS_SAMPLESINK_SDRDAEMONSINK_SDRDAEMONSINKSETTINGS_H_
 | 
			
		||||
 | 
			
		||||
#include <QByteArray>
 | 
			
		||||
 | 
			
		||||
struct SDRdaemonSinkSettings {
 | 
			
		||||
    quint64 m_centerFrequency;
 | 
			
		||||
    quint64 m_sampleRate;
 | 
			
		||||
    quint32 m_log2Interp;
 | 
			
		||||
    QString m_address;
 | 
			
		||||
    quint16 m_port;
 | 
			
		||||
 | 
			
		||||
    SDRdaemonSinkSettings();
 | 
			
		||||
    void resetToDefaults();
 | 
			
		||||
    QByteArray serialize() const;
 | 
			
		||||
    bool deserialize(const QByteArray& data);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* PLUGINS_SAMPLESINK_SDRDAEMONSINK_SDRDAEMONSINKSETTINGS_H_ */
 | 
			
		||||
							
								
								
									
										230
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,230 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2017 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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 <assert.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
#include "dsp/samplesourcefifo.h"
 | 
			
		||||
#include "sdrdaemonsinkthread.h"
 | 
			
		||||
 | 
			
		||||
SDRdaemonSinkThread::SDRdaemonSinkThread(std::ofstream *samplesStream, SampleSourceFifo* sampleFifo, QObject* parent) :
 | 
			
		||||
	QThread(parent),
 | 
			
		||||
	m_running(false),
 | 
			
		||||
	m_ofstream(samplesStream),
 | 
			
		||||
	m_bufsize(0),
 | 
			
		||||
	m_samplesChunkSize(0),
 | 
			
		||||
	m_sampleFifo(sampleFifo),
 | 
			
		||||
	m_samplesCount(0),
 | 
			
		||||
    m_samplerate(0),
 | 
			
		||||
    m_log2Interpolation(0),
 | 
			
		||||
    m_throttlems(SDRDAEMONSINK_THROTTLE_MS),
 | 
			
		||||
    m_throttleToggle(false),
 | 
			
		||||
    m_buf(0),
 | 
			
		||||
    m_maxThrottlems(50)
 | 
			
		||||
{
 | 
			
		||||
    assert(m_ofstream != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SDRdaemonSinkThread::~SDRdaemonSinkThread()
 | 
			
		||||
{
 | 
			
		||||
	if (m_running) {
 | 
			
		||||
		stopWork();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    if (m_buf) delete[] m_buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkThread::startWork()
 | 
			
		||||
{
 | 
			
		||||
	qDebug() << "SDRdaemonSinkThread::startWork: ";
 | 
			
		||||
 | 
			
		||||
    if (m_ofstream->is_open())
 | 
			
		||||
    {
 | 
			
		||||
        qDebug() << "SDRdaemonSinkThread::startWork: file stream open, starting...";
 | 
			
		||||
        m_maxThrottlems = 0;
 | 
			
		||||
        m_startWaitMutex.lock();
 | 
			
		||||
        m_elapsedTimer.start();
 | 
			
		||||
        start();
 | 
			
		||||
        while(!m_running)
 | 
			
		||||
            m_startWaiter.wait(&m_startWaitMutex, 100);
 | 
			
		||||
        m_startWaitMutex.unlock();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        qDebug() << "SDRdaemonSinkThread::startWork: file stream closed, not starting.";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkThread::stopWork()
 | 
			
		||||
{
 | 
			
		||||
	qDebug() << "SDRdaemonSinkThread::stopWork";
 | 
			
		||||
	m_running = false;
 | 
			
		||||
	wait();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkThread::setSamplerate(int samplerate)
 | 
			
		||||
{
 | 
			
		||||
	if (samplerate != m_samplerate)
 | 
			
		||||
	{
 | 
			
		||||
	    qDebug() << "SDRdaemonSinkThread::setSamplerate:"
 | 
			
		||||
	            << " new:" << samplerate
 | 
			
		||||
	            << " old:" << m_samplerate;
 | 
			
		||||
 | 
			
		||||
	    bool wasRunning = false;
 | 
			
		||||
 | 
			
		||||
		if (m_running)
 | 
			
		||||
		{
 | 
			
		||||
			stopWork();
 | 
			
		||||
			wasRunning = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// resize sample FIFO
 | 
			
		||||
		if (m_sampleFifo) {
 | 
			
		||||
		    m_sampleFifo->resize(samplerate); // 1s buffer
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        // resize output buffer
 | 
			
		||||
        if (m_buf) delete[] m_buf;
 | 
			
		||||
        m_buf = new int16_t[samplerate*(1<<m_log2Interpolation)*2];
 | 
			
		||||
 | 
			
		||||
        m_samplerate = samplerate;
 | 
			
		||||
        m_samplesChunkSize = (m_samplerate * m_throttlems) / 1000;
 | 
			
		||||
 | 
			
		||||
        if (wasRunning) {
 | 
			
		||||
            startWork();
 | 
			
		||||
        }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkThread::setLog2Interpolation(int log2Interpolation)
 | 
			
		||||
{
 | 
			
		||||
    if ((log2Interpolation < 0) || (log2Interpolation > 6))
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (log2Interpolation != m_log2Interpolation)
 | 
			
		||||
    {
 | 
			
		||||
        qDebug() << "FileSinkThread::setLog2Interpolation:"
 | 
			
		||||
                << " new:" << log2Interpolation
 | 
			
		||||
                << " old:" << m_log2Interpolation;
 | 
			
		||||
 | 
			
		||||
        bool wasRunning = false;
 | 
			
		||||
 | 
			
		||||
        if (m_running)
 | 
			
		||||
        {
 | 
			
		||||
            stopWork();
 | 
			
		||||
            wasRunning = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // resize output buffer
 | 
			
		||||
        if (m_buf) delete[] m_buf;
 | 
			
		||||
        m_buf = new int16_t[m_samplerate*(1<<log2Interpolation)*2];
 | 
			
		||||
 | 
			
		||||
        m_log2Interpolation = log2Interpolation;
 | 
			
		||||
 | 
			
		||||
        if (wasRunning) {
 | 
			
		||||
            startWork();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkThread::run()
 | 
			
		||||
{
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	m_running = true;
 | 
			
		||||
	m_startWaiter.wakeAll();
 | 
			
		||||
 | 
			
		||||
	while(m_running) // actual work is in the tick() function
 | 
			
		||||
	{
 | 
			
		||||
		sleep(1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_running = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkThread::connectTimer(const QTimer& timer)
 | 
			
		||||
{
 | 
			
		||||
	qDebug() << "SDRdaemonSinkThread::connectTimer";
 | 
			
		||||
	connect(&timer, SIGNAL(timeout()), this, SLOT(tick()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDRdaemonSinkThread::tick()
 | 
			
		||||
{
 | 
			
		||||
	if (m_running)
 | 
			
		||||
	{
 | 
			
		||||
        qint64 throttlems = m_elapsedTimer.restart();
 | 
			
		||||
 | 
			
		||||
        if (throttlems != m_throttlems)
 | 
			
		||||
        {
 | 
			
		||||
            m_throttlems = throttlems;
 | 
			
		||||
            m_samplesChunkSize = (m_samplerate * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000;
 | 
			
		||||
            m_throttleToggle = !m_throttleToggle;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        if (m_throttlems > m_maxThrottlems)
 | 
			
		||||
//        {
 | 
			
		||||
//            qDebug("FileSinkThread::tick: m_maxThrottlems: %d", m_maxThrottlems);
 | 
			
		||||
//            m_maxThrottlems = m_throttlems;
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
        SampleVector::iterator readUntil;
 | 
			
		||||
 | 
			
		||||
        m_sampleFifo->readAdvance(readUntil, m_samplesChunkSize);
 | 
			
		||||
        SampleVector::iterator beginRead = readUntil - m_samplesChunkSize;
 | 
			
		||||
        m_samplesCount += m_samplesChunkSize;
 | 
			
		||||
 | 
			
		||||
        if (m_log2Interpolation == 0)
 | 
			
		||||
        {
 | 
			
		||||
            m_ofstream->write(reinterpret_cast<char*>(&(*beginRead)), m_samplesChunkSize*sizeof(Sample));
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            int chunkSize = std::min((int) m_samplesChunkSize, m_samplerate);
 | 
			
		||||
 | 
			
		||||
            switch (m_log2Interpolation)
 | 
			
		||||
            {
 | 
			
		||||
            case 1:
 | 
			
		||||
                m_interpolators.interpolate2_cen(&beginRead, m_buf, chunkSize*(1<<m_log2Interpolation)*2);
 | 
			
		||||
                break;
 | 
			
		||||
            case 2:
 | 
			
		||||
                m_interpolators.interpolate4_cen(&beginRead, m_buf, chunkSize*(1<<m_log2Interpolation)*2);
 | 
			
		||||
                break;
 | 
			
		||||
            case 3:
 | 
			
		||||
                m_interpolators.interpolate8_cen(&beginRead, m_buf, chunkSize*(1<<m_log2Interpolation)*2);
 | 
			
		||||
                break;
 | 
			
		||||
            case 4:
 | 
			
		||||
                m_interpolators.interpolate16_cen(&beginRead, m_buf, chunkSize*(1<<m_log2Interpolation)*2);
 | 
			
		||||
                break;
 | 
			
		||||
            case 5:
 | 
			
		||||
                m_interpolators.interpolate32_cen(&beginRead, m_buf, chunkSize*(1<<m_log2Interpolation)*2);
 | 
			
		||||
                break;
 | 
			
		||||
            case 6:
 | 
			
		||||
                m_interpolators.interpolate64_cen(&beginRead, m_buf, chunkSize*(1<<m_log2Interpolation)*2);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            m_ofstream->write(reinterpret_cast<char*>(m_buf), m_samplesChunkSize*(1<<m_log2Interpolation)*2*sizeof(int16_t));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								plugins/samplesink/sdrdaemonsink/sdrdaemonsinkthread.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Copyright (C) 2017 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                  //
 | 
			
		||||
//                                                                               //
 | 
			
		||||
// 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_SDRDAEMONSINKTHREAD_H
 | 
			
		||||
#define INCLUDE_SDRDAEMONSINKTHREAD_H
 | 
			
		||||
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QMutex>
 | 
			
		||||
#include <QWaitCondition>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QElapsedTimer>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include "dsp/inthalfbandfilter.h"
 | 
			
		||||
#include "dsp/interpolators.h"
 | 
			
		||||
 | 
			
		||||
#define SDRDAEMONSINK_THROTTLE_MS 50
 | 
			
		||||
 | 
			
		||||
class SampleSourceFifo;
 | 
			
		||||
 | 
			
		||||
class SDRdaemonSinkThread : public QThread {
 | 
			
		||||
	Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	SDRdaemonSinkThread(std::ofstream *samplesStream, SampleSourceFifo* sampleFifo, QObject* parent = 0);
 | 
			
		||||
	~SDRdaemonSinkThread();
 | 
			
		||||
 | 
			
		||||
	void startWork();
 | 
			
		||||
	void stopWork();
 | 
			
		||||
	void setSamplerate(int samplerate);
 | 
			
		||||
	void setLog2Interpolation(int log2Interpolation);
 | 
			
		||||
    void setBuffer(std::size_t chunksize);
 | 
			
		||||
	bool isRunning() const { return m_running; }
 | 
			
		||||
    std::size_t getSamplesCount() const { return m_samplesCount; }
 | 
			
		||||
    void setSamplesCount(int samplesCount) { m_samplesCount = samplesCount; }
 | 
			
		||||
 | 
			
		||||
	void connectTimer(const QTimer& timer);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	QMutex m_startWaitMutex;
 | 
			
		||||
	QWaitCondition m_startWaiter;
 | 
			
		||||
	bool m_running;
 | 
			
		||||
 | 
			
		||||
	std::ofstream* m_ofstream;
 | 
			
		||||
	std::size_t m_bufsize;
 | 
			
		||||
	unsigned int m_samplesChunkSize;
 | 
			
		||||
	SampleSourceFifo* m_sampleFifo;
 | 
			
		||||
    std::size_t m_samplesCount;
 | 
			
		||||
 | 
			
		||||
	int m_samplerate;
 | 
			
		||||
	int m_log2Interpolation;
 | 
			
		||||
    int m_throttlems;
 | 
			
		||||
    int m_maxThrottlems;
 | 
			
		||||
    QElapsedTimer m_elapsedTimer;
 | 
			
		||||
    bool m_throttleToggle;
 | 
			
		||||
 | 
			
		||||
    Interpolators<qint16, SDR_SAMP_SZ, 16> m_interpolators;
 | 
			
		||||
    int16_t *m_buf;
 | 
			
		||||
 | 
			
		||||
	void run();
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
	void tick();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDE_SDRDAEMONSINKTHREAD_H
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user