mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-09-11 19:27:47 -04:00
Merge pull request #26 from cjcliffe/save-load-session
Saving and Loading Sessions
This commit is contained in:
commit
d3cea16fd5
@ -135,6 +135,7 @@ SET (cubicsdr_sources
|
||||
src/util/Timer.cpp
|
||||
src/util/MouseTracker.cpp
|
||||
src/util/GLFont.cpp
|
||||
src/util/DataTree.cpp
|
||||
src/visual/PrimaryGLContext.cpp
|
||||
src/visual/InteractiveCanvas.cpp
|
||||
src/visual/MeterCanvas.cpp
|
||||
@ -151,6 +152,10 @@ SET (cubicsdr_sources
|
||||
src/visual/WaterfallContext.cpp
|
||||
external/rtaudio/RtAudio.cpp
|
||||
external/lodepng/lodepng.cpp
|
||||
external/tinyxml/tinyxml.cpp
|
||||
external/tinyxml/tinystr.cpp
|
||||
external/tinyxml/tinyxmlparser.cpp
|
||||
external/tinyxml/tinyxmlerror.cpp
|
||||
)
|
||||
|
||||
SET (cubicsdr_headers
|
||||
@ -171,6 +176,7 @@ SET (cubicsdr_headers
|
||||
src/util/ThreadQueue.h
|
||||
src/util/MouseTracker.h
|
||||
src/util/GLFont.h
|
||||
src/util/DataTree.h
|
||||
src/visual/PrimaryGLContext.h
|
||||
src/visual/InteractiveCanvas.h
|
||||
src/visual/MeterCanvas.h
|
||||
@ -187,6 +193,8 @@ SET (cubicsdr_headers
|
||||
src/visual/WaterfallContext.h
|
||||
external/rtaudio/RtAudio.h
|
||||
external/lodepng/lodepng.h
|
||||
external/tinyxml/tinyxml.h
|
||||
external/tinyxml/tinystr.h
|
||||
)
|
||||
|
||||
include_directories (
|
||||
@ -198,6 +206,8 @@ include_directories (
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/external/rtaudio
|
||||
${PROJECT_SOURCE_DIR}/external/lodepng
|
||||
${PROJECT_SOURCE_DIR}/external/fastlz
|
||||
${PROJECT_SOURCE_DIR}/external/tinyxml
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS(
|
||||
|
116
external/tinyxml/tinystr.cpp
vendored
Normal file
116
external/tinyxml/tinystr.cpp
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge L?vset, 7. April 2005.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#include "tinystr.h"
|
||||
|
||||
// Error value for find primitive
|
||||
const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
|
||||
|
||||
|
||||
// Null rep.
|
||||
TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
|
||||
|
||||
|
||||
void TiXmlString::reserve (size_type cap)
|
||||
{
|
||||
if (cap > capacity())
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(length(), cap);
|
||||
memcpy(tmp.start(), data(), length());
|
||||
swap(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::assign(const char* str, size_type len)
|
||||
{
|
||||
size_type cap = capacity();
|
||||
if (len > cap || cap > 3*(len + 8))
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(len);
|
||||
memcpy(tmp.start(), str, len);
|
||||
swap(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(start(), str, len);
|
||||
set_size(len);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::append(const char* str, size_type len)
|
||||
{
|
||||
size_type newsize = length() + len;
|
||||
if (newsize > capacity())
|
||||
{
|
||||
reserve (newsize + capacity());
|
||||
}
|
||||
memmove(finish(), str, len);
|
||||
set_size(newsize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.reserve(a.length() + b.length());
|
||||
tmp += a;
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
|
||||
tmp.reserve(a.length() + b_len);
|
||||
tmp += a;
|
||||
tmp.append(b, b_len);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
|
||||
tmp.reserve(a_len + b.length());
|
||||
tmp.append(a, a_len);
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
#endif // TIXML_USE_STL
|
319
external/tinyxml/tinystr.h
vendored
Normal file
319
external/tinyxml/tinystr.h
vendored
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
|
||||
*
|
||||
* - completely rewritten. compact, clean, and fast implementation.
|
||||
* - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
|
||||
* - fixed reserve() to work as per specification.
|
||||
* - fixed buggy compares operator==(), operator<(), and operator>()
|
||||
* - fixed operator+=() to take a const ref argument, following spec.
|
||||
* - added "copy" constructor with length, and most compare operators.
|
||||
* - added swap(), clear(), size(), capacity(), operator+().
|
||||
*/
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#ifndef TIXML_STRING_INCLUDED
|
||||
#define TIXML_STRING_INCLUDED
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* The support for explicit isn't that universal, and it isn't really
|
||||
required - it is used to check that the TiXmlString class isn't incorrectly
|
||||
used. Be nice to old compilers and macro it here:
|
||||
*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
||||
// Microsoft visual studio, version 6 and higher.
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
||||
// GCC version 3 and higher.s
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#else
|
||||
#define TIXML_EXPLICIT
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
TiXmlString is an emulation of a subset of the std::string template.
|
||||
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
||||
Only the member functions relevant to the TinyXML project have been implemented.
|
||||
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
||||
a string and there's no more room, we allocate a buffer twice as big as we need.
|
||||
*/
|
||||
class TiXmlString
|
||||
{
|
||||
public :
|
||||
// The size type used
|
||||
typedef size_t size_type;
|
||||
|
||||
// Error value for find primitive
|
||||
static const size_type npos; // = -1;
|
||||
|
||||
|
||||
// TiXmlString empty constructor
|
||||
TiXmlString () : rep_(&nullrep_)
|
||||
{
|
||||
}
|
||||
|
||||
// TiXmlString copy constructor
|
||||
TiXmlString ( const TiXmlString & copy) : rep_(0)
|
||||
{
|
||||
init(copy.length());
|
||||
memcpy(start(), copy.data(), length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
|
||||
{
|
||||
init( static_cast<size_type>( strlen(copy) ));
|
||||
memcpy(start(), copy, length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
|
||||
{
|
||||
init(len);
|
||||
memcpy(start(), str, len);
|
||||
}
|
||||
|
||||
// TiXmlString destructor
|
||||
~TiXmlString ()
|
||||
{
|
||||
quit();
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const char * copy)
|
||||
{
|
||||
return assign( copy, (size_type)strlen(copy));
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const TiXmlString & copy)
|
||||
{
|
||||
return assign(copy.start(), copy.length());
|
||||
}
|
||||
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const char * suffix)
|
||||
{
|
||||
return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (char single)
|
||||
{
|
||||
return append(&single, 1);
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const TiXmlString & suffix)
|
||||
{
|
||||
return append(suffix.data(), suffix.length());
|
||||
}
|
||||
|
||||
|
||||
// Convert a TiXmlString into a null-terminated char *
|
||||
const char * c_str () const { return rep_->str; }
|
||||
|
||||
// Convert a TiXmlString into a char * (need not be null terminated).
|
||||
const char * data () const { return rep_->str; }
|
||||
|
||||
// Return the length of a TiXmlString
|
||||
size_type length () const { return rep_->size; }
|
||||
|
||||
// Alias for length()
|
||||
size_type size () const { return rep_->size; }
|
||||
|
||||
// Checks if a TiXmlString is empty
|
||||
bool empty () const { return rep_->size == 0; }
|
||||
|
||||
// Return capacity of string
|
||||
size_type capacity () const { return rep_->capacity; }
|
||||
|
||||
|
||||
// single char extraction
|
||||
const char& at (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// [] operator
|
||||
char& operator [] (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// find a char in a string. Return TiXmlString::npos if not found
|
||||
size_type find (char lookup) const
|
||||
{
|
||||
return find(lookup, 0);
|
||||
}
|
||||
|
||||
// find a char in a string from an offset. Return TiXmlString::npos if not found
|
||||
size_type find (char tofind, size_type offset) const
|
||||
{
|
||||
if (offset >= length()) return npos;
|
||||
|
||||
for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
//Lee:
|
||||
//The original was just too strange, though correct:
|
||||
// TiXmlString().swap(*this);
|
||||
//Instead use the quit & re-init:
|
||||
quit();
|
||||
init(0,0);
|
||||
}
|
||||
|
||||
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
||||
function DOES NOT clear the content of the TiXmlString if any exists.
|
||||
*/
|
||||
void reserve (size_type cap);
|
||||
|
||||
TiXmlString& assign (const char* str, size_type len);
|
||||
|
||||
TiXmlString& append (const char* str, size_type len);
|
||||
|
||||
void swap (TiXmlString& other)
|
||||
{
|
||||
Rep* r = rep_;
|
||||
rep_ = other.rep_;
|
||||
other.rep_ = r;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init(size_type sz) { init(sz, sz); }
|
||||
void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
||||
char* start() const { return rep_->str; }
|
||||
char* finish() const { return rep_->str + rep_->size; }
|
||||
|
||||
struct Rep
|
||||
{
|
||||
size_type size, capacity;
|
||||
char str[1];
|
||||
};
|
||||
|
||||
void init(size_type sz, size_type cap)
|
||||
{
|
||||
if (cap)
|
||||
{
|
||||
// Lee: the original form:
|
||||
// rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
||||
// doesn't work in some cases of new being overloaded. Switching
|
||||
// to the normal allocation, although use an 'int' for systems
|
||||
// that are overly picky about structure alignment.
|
||||
const size_type bytesNeeded = sizeof(Rep) + cap;
|
||||
const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
||||
rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
||||
|
||||
rep_->str[ rep_->size = sz ] = '\0';
|
||||
rep_->capacity = cap;
|
||||
}
|
||||
else
|
||||
{
|
||||
rep_ = &nullrep_;
|
||||
}
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
if (rep_ != &nullrep_)
|
||||
{
|
||||
// The rep_ is really an array of ints. (see the allocator, above).
|
||||
// Cast it back before delete, so the compiler won't incorrectly call destructors.
|
||||
delete [] ( reinterpret_cast<int*>( rep_ ) );
|
||||
}
|
||||
}
|
||||
|
||||
Rep * rep_;
|
||||
static Rep nullrep_;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return ( a.length() == b.length() ) // optimization on some platforms
|
||||
&& ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
||||
}
|
||||
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return strcmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
||||
inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
||||
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
||||
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
||||
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
||||
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
||||
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b);
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b);
|
||||
|
||||
|
||||
/*
|
||||
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
||||
Only the operators that we need for TinyXML have been developped.
|
||||
*/
|
||||
class TiXmlOutStream : public TiXmlString
|
||||
{
|
||||
public :
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const TiXmlString & in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const char * in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
#endif // TIXML_STRING_INCLUDED
|
||||
#endif // TIXML_USE_STL
|
1888
external/tinyxml/tinyxml.cpp
vendored
Normal file
1888
external/tinyxml/tinyxml.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1802
external/tinyxml/tinyxml.h
vendored
Normal file
1802
external/tinyxml/tinyxml.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
53
external/tinyxml/tinyxmlerror.cpp
vendored
Normal file
53
external/tinyxml/tinyxmlerror.cpp
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
// The goal of the seperate error file is to make the first
|
||||
// step towards localization. tinyxml (currently) only supports
|
||||
// english error messages, but the could now be translated.
|
||||
//
|
||||
// It also cleans up the code a bit.
|
||||
//
|
||||
|
||||
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
|
||||
{
|
||||
"No error",
|
||||
"Error",
|
||||
"Failed to open file",
|
||||
"Memory allocation failed.",
|
||||
"Error parsing Element.",
|
||||
"Failed to read Element name",
|
||||
"Error reading Element value.",
|
||||
"Error reading Attributes.",
|
||||
"Error: empty tag.",
|
||||
"Error reading end tag.",
|
||||
"Error parsing Unknown.",
|
||||
"Error parsing Comment.",
|
||||
"Error parsing Declaration.",
|
||||
"Error document empty.",
|
||||
"Error null (0) or unexpected EOF found in input stream.",
|
||||
"Error parsing CDATA.",
|
||||
"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
|
||||
};
|
1638
external/tinyxml/tinyxmlparser.cpp
vendored
Normal file
1638
external/tinyxml/tinyxmlparser.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1294
external/tinyxml/xmltest.cpp
vendored
Normal file
1294
external/tinyxml/xmltest.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
174
src/AppFrame.cpp
174
src/AppFrame.cpp
@ -7,6 +7,7 @@
|
||||
#endif
|
||||
|
||||
#include "wx/numdlg.h"
|
||||
#include "wx/filedlg.h"
|
||||
|
||||
#if !wxUSE_GLCANVAS
|
||||
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
||||
@ -17,6 +18,7 @@
|
||||
#include "DemodulatorMgr.h"
|
||||
#include "AudioThread.h"
|
||||
#include "CubicSDR.h"
|
||||
#include "DataTree.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
@ -26,13 +28,12 @@ wxBEGIN_EVENT_TABLE(AppFrame, wxFrame)
|
||||
//EVT_MENU(wxID_NEW, AppFrame::OnNewWindow)
|
||||
EVT_MENU(wxID_CLOSE, AppFrame::OnClose)
|
||||
EVT_MENU(wxID_ANY, AppFrame::OnMenu)
|
||||
|
||||
EVT_COMMAND(wxID_ANY, wxEVT_THREAD, AppFrame::OnThread)
|
||||
EVT_IDLE(AppFrame::OnIdle)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
AppFrame::AppFrame() :
|
||||
wxFrame(NULL, wxID_ANY, wxT("CubicSDR v0.1a by Charles J. Cliffe (@ccliffe)")), activeDemodulator(NULL) {
|
||||
wxFrame(NULL, wxID_ANY, wxT("CubicSDR " CUBICSDR_VERSION " by Charles J. Cliffe (@ccliffe)")), activeDemodulator(NULL) {
|
||||
|
||||
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
|
||||
@ -40,12 +41,12 @@ AppFrame::AppFrame() :
|
||||
wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
|
||||
demodModeSelector = new ModeSelectorCanvas(this, NULL);
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_FM,"FM");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_AM,"AM");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_LSB,"LSB");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_USB,"USB");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_AM, "AM");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_LSB, "LSB");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_USB, "USB");
|
||||
demodModeSelector->addChoice(DEMOD_TYPE_DSB, "DSB");
|
||||
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
|
||||
|
||||
// demodTray->AddSpacer(2);
|
||||
@ -110,7 +111,11 @@ AppFrame::AppFrame() :
|
||||
wxMenu *menu = new wxMenu;
|
||||
// menu->Append(wxID_NEW);
|
||||
menu->Append(wxID_SET_FREQ_OFFSET, "Set Frequency Offset");
|
||||
menu->Append(wxID_OPEN, "&Open Session");
|
||||
menu->Append(wxID_SAVE, "&Save Session");
|
||||
menu->Append(wxID_SAVEAS, "Save Session &As..");
|
||||
menu->AppendSeparator();
|
||||
menu->Append(wxID_RESET, "&Reset Session");
|
||||
menu->Append(wxID_CLOSE);
|
||||
|
||||
menuBar->Append(menu, wxT("&File"));
|
||||
@ -155,6 +160,14 @@ AppFrame::AppFrame() :
|
||||
|
||||
GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), DEFAULT_FREQ));
|
||||
|
||||
wxAcceleratorEntry entries[3];
|
||||
entries[0].Set(wxACCEL_CTRL, (int) 'O', wxID_OPEN);
|
||||
entries[1].Set(wxACCEL_CTRL, (int) 'S', wxID_SAVE);
|
||||
entries[2].Set(wxACCEL_CTRL, (int) 'A', wxID_SAVEAS);
|
||||
|
||||
wxAcceleratorTable accel(3, entries);
|
||||
SetAcceleratorTable(accel);
|
||||
|
||||
// static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
|
||||
// wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
|
||||
// ShowFullScreen(true);
|
||||
@ -171,15 +184,44 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||
activeDemodulator = NULL;
|
||||
}
|
||||
} else if (event.GetId() == wxID_SET_FREQ_OFFSET) {
|
||||
long ofs = wxGetNumberFromUser ("Shift the displayed frequency by this amount.\ni.e. -125000000 for -125 MHz", "Frequency (Hz)", "Frequency Offset", wxGetApp().getOffset(), -2000000000, 2000000000, this);
|
||||
long ofs = wxGetNumberFromUser("Shift the displayed frequency by this amount.\ni.e. -125000000 for -125 MHz", "Frequency (Hz)",
|
||||
"Frequency Offset", wxGetApp().getOffset(), -2000000000, 2000000000, this);
|
||||
if (ofs != -1) {
|
||||
wxGetApp().setOffset(ofs);
|
||||
}
|
||||
} else if (event.GetId() == wxID_SAVE) {
|
||||
if (!currentSessionFile.empty()) {
|
||||
saveSession(currentSessionFile);
|
||||
} else {
|
||||
wxFileDialog saveFileDialog(this, _("Save XML Session file"), "", "", "XML files (*.xml)|*.xml", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if (saveFileDialog.ShowModal() == wxID_CANCEL) {
|
||||
return;
|
||||
}
|
||||
saveSession(saveFileDialog.GetPath().ToStdString());
|
||||
}
|
||||
} else if (event.GetId() == wxID_OPEN) {
|
||||
wxFileDialog openFileDialog(this, _("Open XML Session file"), "", "", "XML files (*.xml)|*.xml", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (openFileDialog.ShowModal() == wxID_CANCEL) {
|
||||
return;
|
||||
}
|
||||
loadSession(openFileDialog.GetPath().ToStdString());
|
||||
} else if (event.GetId() == wxID_SAVEAS) {
|
||||
wxFileDialog saveFileDialog(this, _("Save XML Session file"), "", "", "XML files (*.xml)|*.xml", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if (saveFileDialog.ShowModal() == wxID_CANCEL) {
|
||||
return;
|
||||
}
|
||||
saveSession(saveFileDialog.GetPath().ToStdString());
|
||||
} else if (event.GetId() == wxID_RESET) {
|
||||
wxGetApp().getDemodMgr().terminateAll();
|
||||
wxGetApp().setFrequency(DEFAULT_FREQ);
|
||||
wxGetApp().setOffset(0);
|
||||
} else if (event.GetId() == wxID_EXIT) {
|
||||
Close(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) {
|
||||
Close(true);
|
||||
Close(false);
|
||||
}
|
||||
|
||||
void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
|
||||
@ -281,3 +323,117 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
void AppFrame::saveSession(std::string fileName) {
|
||||
DataTree s("cubicsdr_session");
|
||||
DataNode *header = s.rootNode()->newChild("header");
|
||||
*header->newChild("version") = std::string(CUBICSDR_VERSION);
|
||||
*header->newChild("center_freq") = wxGetApp().getFrequency();
|
||||
*header->newChild("offset") = wxGetApp().getOffset();
|
||||
|
||||
DataNode *demods = s.rootNode()->newChild("demodulators");
|
||||
|
||||
std::vector<DemodulatorInstance *> &instances = wxGetApp().getDemodMgr().getDemodulators();
|
||||
std::vector<DemodulatorInstance *>::iterator instance_i;
|
||||
for (instance_i = instances.begin(); instance_i != instances.end(); instance_i++) {
|
||||
DataNode *demod = demods->newChild("demodulator");
|
||||
*demod->newChild("bandwidth") = (*instance_i)->getBandwidth();
|
||||
*demod->newChild("frequency") = (*instance_i)->getFrequency();
|
||||
*demod->newChild("type") = (*instance_i)->getDemodulatorType();
|
||||
*demod->newChild("squelch_level") = (*instance_i)->getSquelchLevel();
|
||||
*demod->newChild("squelch_enabled") = (*instance_i)->isSquelchEnabled() ? 1 : 0;
|
||||
*demod->newChild("stereo") = (*instance_i)->isStereo() ? 1 : 0;
|
||||
*demod->newChild("output_device") = outputDevices[(*instance_i)->getOutputDevice()].name;
|
||||
}
|
||||
|
||||
s.SaveToFileXML(fileName);
|
||||
}
|
||||
|
||||
bool AppFrame::loadSession(std::string fileName) {
|
||||
DataTree l;
|
||||
if (!l.LoadFromFileXML(fileName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wxGetApp().getDemodMgr().terminateAll();
|
||||
|
||||
try {
|
||||
DataNode *header = l.rootNode()->getNext("header");
|
||||
|
||||
std::string version(*header->getNext("version"));
|
||||
long long center_freq = *header->getNext("center_freq");
|
||||
long long offset = *header->getNext("offset");
|
||||
|
||||
std::cout << "Loading " << version << " session file" << std::endl;
|
||||
std::cout << "\tCenter Frequency: " << center_freq << std::endl;
|
||||
std::cout << "\tOffset: " << offset << std::endl;
|
||||
|
||||
wxGetApp().setOffset(offset);
|
||||
wxGetApp().setFrequency(center_freq);
|
||||
|
||||
DataNode *demodulators = l.rootNode()->getNext("demodulators");
|
||||
|
||||
while (demodulators->hasAnother("demodulator")) {
|
||||
DataNode *demod = demodulators->getNext("demodulator");
|
||||
|
||||
if (!demod->hasAnother("bandwidth") || !demod->hasAnother("frequency")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long bandwidth = *demod->getNext("bandwidth");
|
||||
long long freq = *demod->getNext("frequency");
|
||||
int type = demod->hasAnother("type") ? *demod->getNext("type") : DEMOD_TYPE_FM;
|
||||
float squelch_level = demod->hasAnother("squelch_level") ? (float) *demod->getNext("squelch_level") : 0;
|
||||
int squelch_enabled = demod->hasAnother("squelch_enabled") ? (int) *demod->getNext("squelch_enabled") : 0;
|
||||
int stereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 0;
|
||||
std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : "";
|
||||
|
||||
DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread();
|
||||
newDemod->setDemodulatorType(type);
|
||||
newDemod->setBandwidth(bandwidth);
|
||||
newDemod->setFrequency(freq);
|
||||
newDemod->updateLabel(freq);
|
||||
if (squelch_enabled) {
|
||||
newDemod->setSquelchEnabled(true);
|
||||
newDemod->setSquelchLevel(squelch_level);
|
||||
}
|
||||
if (stereo) {
|
||||
newDemod->setStereo(true);
|
||||
}
|
||||
|
||||
bool found_device = false;
|
||||
std::map<int, RtAudio::DeviceInfo>::iterator i;
|
||||
for (i = outputDevices.begin(); i != outputDevices.end(); i++) {
|
||||
if (i->second.name == output_device) {
|
||||
newDemod->setOutputDevice(i->first);
|
||||
found_device = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_device) {
|
||||
std::cout << "\tWarning: named output device '" << output_device << "' was not found. Using default output.";
|
||||
}
|
||||
|
||||
newDemod->run();
|
||||
|
||||
wxGetApp().bindDemodulator(newDemod);
|
||||
|
||||
std::cout << "\tAdded demodulator at frequency " << freq << " type " << type << std::endl;
|
||||
std::cout << "\t\tBandwidth: " << bandwidth << std::endl;
|
||||
std::cout << "\t\tSquelch Level: " << squelch_level << std::endl;
|
||||
std::cout << "\t\tSquelch Enabled: " << (squelch_enabled ? "true" : "false") << std::endl;
|
||||
std::cout << "\t\tStereo: " << (stereo ? "true" : "false") << std::endl;
|
||||
std::cout << "\t\tOutput Device: " << output_device << std::endl;
|
||||
|
||||
}
|
||||
|
||||
} catch (DataInvalidChildException &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return false;
|
||||
} catch (DataTypeMismatchException &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
currentSessionFile = fileName;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#define wxID_RT_AUDIO_DEVICE 1000
|
||||
#define wxID_SET_FREQ_OFFSET 2001
|
||||
#define wxID_RESET 2002
|
||||
|
||||
// Define a new frame type
|
||||
class AppFrame: public wxFrame {
|
||||
@ -23,6 +24,9 @@ public:
|
||||
void OnThread(wxCommandEvent& event);
|
||||
void OnEventInput(wxThreadEvent& event);
|
||||
|
||||
void saveSession(std::string fileName);
|
||||
bool loadSession(std::string fileName);
|
||||
|
||||
private:
|
||||
void OnMenu(wxCommandEvent& event);
|
||||
void OnClose(wxCommandEvent& event);
|
||||
@ -46,5 +50,7 @@ private:
|
||||
std::map<int,RtAudio::DeviceInfo> outputDevices;
|
||||
std::map<int,wxMenuItem *> outputDeviceMenuItems;
|
||||
|
||||
std::string currentSessionFile;
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define CUBICSDR_VERSION "v0.01a"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define BUF_SIZE (16384*2)
|
||||
#define SRATE 2000000
|
||||
@ -9,8 +11,7 @@
|
||||
#endif
|
||||
#define DEFAULT_FFT_SIZE 2048
|
||||
|
||||
//#define DEFAULT_FREQ 98900000
|
||||
#define DEFAULT_FREQ 132000000
|
||||
#define DEFAULT_FREQ 100000000
|
||||
#define AUDIO_FREQUENCY 44100
|
||||
|
||||
#include <mutex>
|
||||
|
@ -10,8 +10,8 @@ std::map<int, std::thread *> AudioThread::deviceThread;
|
||||
#endif
|
||||
|
||||
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
|
||||
currentInput(NULL), inputQueue(inputQueue), audioQueuePtr(0), underflowCount(0), terminated(false), active(false), outputDevice(-1), gain(1.0), threadQueueNotify(
|
||||
threadQueueNotify) {
|
||||
currentInput(NULL), inputQueue(inputQueue), audioQueuePtr(0), underflowCount(0), terminated(false), active(false), outputDevice(-1), gain(
|
||||
1.0), threadQueueNotify(threadQueueNotify) {
|
||||
#ifdef __APPLE__
|
||||
boundThreads = new std::vector<AudioThread *>;
|
||||
#endif
|
||||
@ -72,6 +72,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
continue;
|
||||
}
|
||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||
if (srcmix->terminated) {
|
||||
continue;
|
||||
}
|
||||
srcmix->audioQueuePtr = 0;
|
||||
continue;
|
||||
}
|
||||
@ -88,6 +91,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
continue;
|
||||
}
|
||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||
if (srcmix->terminated) {
|
||||
continue;
|
||||
}
|
||||
srcmix->audioQueuePtr = 0;
|
||||
}
|
||||
continue;
|
||||
@ -104,6 +110,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
continue;
|
||||
}
|
||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||
if (srcmix->terminated) {
|
||||
continue;
|
||||
}
|
||||
srcmix->audioQueuePtr = 0;
|
||||
}
|
||||
if (srcmix->currentInput && srcmix->currentInput->data.size()) {
|
||||
@ -124,6 +133,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
continue;
|
||||
}
|
||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||
if (srcmix->terminated) {
|
||||
continue;
|
||||
}
|
||||
srcmix->audioQueuePtr = 0;
|
||||
}
|
||||
if (srcmix->currentInput && srcmix->currentInput->data.size()) {
|
||||
@ -151,6 +163,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
|
||||
if (!src->currentInput) {
|
||||
src->inputQueue->pop(src->currentInput);
|
||||
if (src->terminated) {
|
||||
return 1;
|
||||
}
|
||||
src->audioQueuePtr = 0;
|
||||
return 0;
|
||||
}
|
||||
@ -167,6 +182,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
return 1;
|
||||
}
|
||||
src->inputQueue->pop(src->currentInput);
|
||||
if (src->terminated) {
|
||||
return 1;
|
||||
}
|
||||
src->audioQueuePtr = 0;
|
||||
}
|
||||
return 0;
|
||||
@ -183,6 +201,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
return 1;
|
||||
}
|
||||
src->inputQueue->pop(src->currentInput);
|
||||
if (src->terminated) {
|
||||
return 1;
|
||||
}
|
||||
src->audioQueuePtr = 0;
|
||||
}
|
||||
if (src->currentInput && src->currentInput->data.size()) {
|
||||
@ -201,6 +222,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
||||
return 1;
|
||||
}
|
||||
src->inputQueue->pop(src->currentInput);
|
||||
if (src->terminated) {
|
||||
return 1;
|
||||
}
|
||||
src->audioQueuePtr = 0;
|
||||
}
|
||||
if (src->currentInput && src->currentInput->data.size()) {
|
||||
@ -344,10 +368,12 @@ void AudioThread::threadMain() {
|
||||
return;
|
||||
}
|
||||
|
||||
setupDevice((outputDevice.load() == -1)?(dac.getDefaultOutputDevice()):outputDevice.load());
|
||||
setupDevice((outputDevice.load() == -1) ? (dac.getDefaultOutputDevice()) : outputDevice.load());
|
||||
|
||||
std::cout << "Audio thread started." << std::endl;
|
||||
|
||||
terminated = false;
|
||||
|
||||
while (!terminated) {
|
||||
AudioThreadCommand command;
|
||||
cmdQueue.pop(command);
|
||||
@ -357,29 +383,35 @@ void AudioThread::threadMain() {
|
||||
}
|
||||
}
|
||||
|
||||
AudioThreadInput dummy;
|
||||
inputQueue->push(&dummy);
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (deviceController[parameters.deviceId] != this) {
|
||||
deviceController[parameters.deviceId]->removeThread(this);
|
||||
} else {
|
||||
try {
|
||||
dac.stopStream();
|
||||
dac.closeStream();
|
||||
if (dac.isStreamOpen()) {
|
||||
if (dac.isStreamRunning()) {
|
||||
dac.stopStream();
|
||||
}
|
||||
dac.closeStream();
|
||||
}
|
||||
} catch (RtAudioError& e) {
|
||||
e.printMessage();
|
||||
}
|
||||
}
|
||||
#else
|
||||
try {
|
||||
// Stop the stream
|
||||
dac.stopStream();
|
||||
dac.closeStream();
|
||||
if (dac.isStreamOpen()) {
|
||||
if (dac.isStreamRunning()) {
|
||||
dac.stopStream();
|
||||
}
|
||||
dac.closeStream();
|
||||
}
|
||||
} catch (RtAudioError& e) {
|
||||
e.printMessage();
|
||||
}
|
||||
|
||||
if (dac.isStreamOpen()) {
|
||||
dac.closeStream();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::cout << "Audio thread done." << std::endl;
|
||||
@ -425,7 +457,6 @@ void AudioThread::setActive(bool state) {
|
||||
active = state;
|
||||
}
|
||||
|
||||
|
||||
AudioThreadCommandQueue *AudioThread::getCommandQueue() {
|
||||
return &cmdQueue;
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
std::atomic<unsigned int> audioQueuePtr;
|
||||
std::atomic<unsigned int> underflowCount;
|
||||
std::atomic<bool> terminated;
|
||||
std::atomic<bool> initialized;
|
||||
std::atomic<bool> active;
|
||||
std::atomic<int> outputDevice;
|
||||
float gain;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define DEMOD_TYPE_AM 2
|
||||
#define DEMOD_TYPE_LSB 3
|
||||
#define DEMOD_TYPE_USB 4
|
||||
#define DEMOD_TYPE_DSB 5
|
||||
|
||||
|
||||
class DemodulatorThread;
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "DemodulatorInstance.h"
|
||||
|
||||
DemodulatorInstance::DemodulatorInstance() :
|
||||
t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(false), audioTerminated(false), demodTerminated(
|
||||
false), preDemodTerminated(false), active(false), squelch(false), stereo(false), currentFrequency(0), currentBandwidth(0) {
|
||||
t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(true), audioTerminated(true), demodTerminated(
|
||||
true), preDemodTerminated(true), active(false), squelch(false), stereo(false), currentFrequency(0), currentBandwidth(0) {
|
||||
|
||||
label = new std::string("Unnamed");
|
||||
threadQueueDemod = new DemodulatorThreadInputQueue;
|
||||
@ -26,9 +26,13 @@ DemodulatorInstance::DemodulatorInstance() :
|
||||
DemodulatorInstance::~DemodulatorInstance() {
|
||||
delete audioThread;
|
||||
delete demodulatorThread;
|
||||
|
||||
delete audioInputQueue;
|
||||
delete demodulatorPreThread;
|
||||
delete threadQueueDemod;
|
||||
delete threadQueuePostDemod;
|
||||
delete threadQueueCommand;
|
||||
delete threadQueueNotify;
|
||||
delete threadQueueControl;
|
||||
delete audioInputQueue;
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
|
||||
@ -36,7 +40,16 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQu
|
||||
}
|
||||
|
||||
void DemodulatorInstance::run() {
|
||||
if (active) {
|
||||
return;
|
||||
}
|
||||
|
||||
// while (!isTerminated()) {
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
// }
|
||||
|
||||
currentFrequency = demodulatorPreThread->getParams().frequency;
|
||||
currentDemodType = demodulatorThread->getDemodulatorType();
|
||||
|
||||
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
|
||||
|
||||
@ -63,6 +76,8 @@ void DemodulatorInstance::run() {
|
||||
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
|
||||
#endif
|
||||
active = true;
|
||||
audioTerminated = demodTerminated = preDemodTerminated = terminated = false;
|
||||
|
||||
}
|
||||
|
||||
void DemodulatorInstance::updateLabel(long long freq) {
|
||||
@ -109,12 +124,10 @@ bool DemodulatorInstance::isTerminated() {
|
||||
|
||||
switch (cmd.cmd) {
|
||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED:
|
||||
audioThread = NULL;
|
||||
t_Audio->join();
|
||||
audioTerminated = true;
|
||||
break;
|
||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED:
|
||||
demodulatorThread = NULL;
|
||||
#ifdef __APPLE__
|
||||
pthread_join(t_Demod, NULL);
|
||||
#else
|
||||
@ -123,7 +136,6 @@ bool DemodulatorInstance::isTerminated() {
|
||||
demodTerminated = true;
|
||||
break;
|
||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED:
|
||||
demodulatorPreThread = NULL;
|
||||
#ifdef __APPLE__
|
||||
pthread_join(t_PreDemod, NULL);
|
||||
#else
|
||||
@ -146,8 +158,12 @@ bool DemodulatorInstance::isActive() {
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setActive(bool state) {
|
||||
if (active && !state) {
|
||||
audioThread->setActive(state);
|
||||
} else if (!active && state) {
|
||||
audioThread->setActive(state);
|
||||
}
|
||||
active = state;
|
||||
audioThread->setActive(state);
|
||||
}
|
||||
|
||||
bool DemodulatorInstance::isStereo() {
|
||||
@ -197,7 +213,9 @@ float DemodulatorInstance::getSquelchLevel() {
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setOutputDevice(int device_id) {
|
||||
if (audioThread) {
|
||||
if (!active) {
|
||||
audioThread->setInitOutputDevice(device_id);
|
||||
} else if (audioThread) {
|
||||
AudioThreadCommand command;
|
||||
command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE;
|
||||
command.int_value = device_id;
|
||||
@ -216,7 +234,12 @@ void DemodulatorInstance::checkBandwidth() {
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setDemodulatorType(int demod_type_in) {
|
||||
if (demodulatorThread && threadQueueControl) {
|
||||
if (!active) {
|
||||
currentDemodType = demod_type_in;
|
||||
checkBandwidth();
|
||||
demodulatorPreThread->getParams().demodType = currentDemodType;
|
||||
demodulatorThread->setDemodulatorType(currentDemodType);
|
||||
} else if (demodulatorThread && threadQueueControl) {
|
||||
DemodulatorThreadControlCommand command;
|
||||
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
|
||||
currentDemodType = demod_type_in;
|
||||
@ -231,7 +254,11 @@ int DemodulatorInstance::getDemodulatorType() {
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setBandwidth(int bw) {
|
||||
if (demodulatorPreThread && threadQueueCommand) {
|
||||
if (!active) {
|
||||
currentBandwidth = bw;
|
||||
checkBandwidth();
|
||||
demodulatorPreThread->getParams().bandwidth = currentBandwidth;
|
||||
} else if (demodulatorPreThread && threadQueueCommand) {
|
||||
DemodulatorThreadCommand command;
|
||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
|
||||
currentBandwidth = bw;
|
||||
@ -239,7 +266,6 @@ void DemodulatorInstance::setBandwidth(int bw) {
|
||||
command.llong_value = currentBandwidth;
|
||||
threadQueueCommand->push(command);
|
||||
}
|
||||
demodulatorPreThread->getParams().bandwidth;
|
||||
}
|
||||
|
||||
int DemodulatorInstance::getBandwidth() {
|
||||
@ -250,17 +276,20 @@ int DemodulatorInstance::getBandwidth() {
|
||||
}
|
||||
|
||||
void DemodulatorInstance::setFrequency(long long freq) {
|
||||
if ((freq - getBandwidth()/2) <= 0) {
|
||||
freq = getBandwidth()/2;
|
||||
if ((freq - getBandwidth() / 2) <= 0) {
|
||||
freq = getBandwidth() / 2;
|
||||
}
|
||||
if (demodulatorPreThread && threadQueueCommand) {
|
||||
DemodulatorThreadCommand command;
|
||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
|
||||
currentFrequency = freq;
|
||||
command.llong_value = freq;
|
||||
threadQueueCommand->push(command);
|
||||
}
|
||||
demodulatorPreThread->getParams().bandwidth;
|
||||
if (!active) {
|
||||
currentFrequency = freq;
|
||||
demodulatorPreThread->getParams().frequency = currentFrequency;
|
||||
} else if (demodulatorPreThread && threadQueueCommand) {
|
||||
DemodulatorThreadCommand command;
|
||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
|
||||
currentFrequency = freq;
|
||||
command.llong_value = freq;
|
||||
threadQueueCommand->push(command);
|
||||
}
|
||||
demodulatorPreThread->getParams().bandwidth;
|
||||
}
|
||||
|
||||
long long DemodulatorInstance::getFrequency() {
|
||||
|
@ -29,6 +29,7 @@ DemodulatorInstance *DemodulatorMgr::newThread() {
|
||||
void DemodulatorMgr::terminateAll() {
|
||||
while (demods.size()) {
|
||||
DemodulatorInstance *d = demods.back();
|
||||
wxGetApp().removeDemodulator(d);
|
||||
deleteThread(d);
|
||||
}
|
||||
}
|
||||
@ -54,8 +55,8 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
|
||||
|
||||
if (i != demods.end()) {
|
||||
demods.erase(i);
|
||||
demod->terminate();
|
||||
}
|
||||
demod->terminate();
|
||||
|
||||
demods_deleted.push_back(demod);
|
||||
|
||||
|
@ -70,6 +70,8 @@ void DemodulatorPreThread::threadMain() {
|
||||
std::vector<liquid_float_complex> in_buf_data;
|
||||
std::vector<liquid_float_complex> out_buf_data;
|
||||
|
||||
terminated = false;
|
||||
|
||||
while (!terminated) {
|
||||
DemodulatorThreadIQData *inp;
|
||||
iqInputQueue->pop(inp);
|
||||
|
@ -32,6 +32,10 @@ public:
|
||||
return params;
|
||||
}
|
||||
|
||||
void setParams(DemodulatorThreadParameters ¶ms_in) {
|
||||
params = params_in;
|
||||
}
|
||||
|
||||
void initialize();
|
||||
void terminate();
|
||||
|
||||
|
@ -16,6 +16,7 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQue
|
||||
demodFM = freqdem_create(0.5);
|
||||
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
|
||||
demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
|
||||
demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
|
||||
demodAM_DSB_CSP = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
||||
demodAM = demodAM_DSB_CSP;
|
||||
|
||||
@ -91,6 +92,8 @@ void DemodulatorThread::threadMain() {
|
||||
|
||||
std::cout << "Demodulator thread started.." << std::endl;
|
||||
|
||||
terminated = false;
|
||||
|
||||
while (!terminated) {
|
||||
DemodulatorThreadPostIQData *inp;
|
||||
iqInputQueue->pop(inp);
|
||||
@ -112,9 +115,9 @@ void DemodulatorThread::threadMain() {
|
||||
audioResampler = inp->audioResampler;
|
||||
stereoResampler = inp->stereoResampler;
|
||||
|
||||
ampmodem_reset(demodAM_USB);
|
||||
ampmodem_reset(demodAM_LSB);
|
||||
ampmodem_reset(demodAM_DSB_CSP);
|
||||
if (demodAM) {
|
||||
ampmodem_reset(demodAM);
|
||||
}
|
||||
freqdem_reset(demodFM);
|
||||
}
|
||||
|
||||
@ -174,6 +177,7 @@ void DemodulatorThread::threadMain() {
|
||||
}
|
||||
break;
|
||||
case DEMOD_TYPE_AM:
|
||||
case DEMOD_TYPE_DSB:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -350,15 +354,23 @@ void DemodulatorThread::threadMain() {
|
||||
if (newDemodType != DEMOD_TYPE_NULL) {
|
||||
switch (newDemodType) {
|
||||
case DEMOD_TYPE_FM:
|
||||
freqdem_reset(demodFM);
|
||||
break;
|
||||
case DEMOD_TYPE_LSB:
|
||||
demodAM = demodAM_USB;
|
||||
ampmodem_reset(demodAM);
|
||||
break;
|
||||
case DEMOD_TYPE_USB:
|
||||
demodAM = demodAM_LSB;
|
||||
ampmodem_reset(demodAM);
|
||||
break;
|
||||
case DEMOD_TYPE_DSB:
|
||||
demodAM = demodAM_DSB;
|
||||
ampmodem_reset(demodAM);
|
||||
break;
|
||||
case DEMOD_TYPE_AM:
|
||||
demodAM = demodAM_DSB_CSP;
|
||||
ampmodem_reset(demodAM);
|
||||
break;
|
||||
}
|
||||
demodulatorType = newDemodType;
|
||||
|
@ -62,6 +62,7 @@ protected:
|
||||
freqdem demodFM;
|
||||
ampmodem demodAM;
|
||||
ampmodem demodAM_DSB_CSP;
|
||||
ampmodem demodAM_DSB;
|
||||
ampmodem demodAM_LSB;
|
||||
ampmodem demodAM_USB;
|
||||
|
||||
|
@ -130,9 +130,8 @@ void SDRPostThread::threadMain() {
|
||||
std::vector<DemodulatorInstance *>::iterator i;
|
||||
for (i = demodulators.begin(); i != demodulators.end(); i++) {
|
||||
DemodulatorInstance *demod = *i;
|
||||
|
||||
if (demod->getParams().frequency != data_in->frequency
|
||||
&& abs(data_in->frequency - demod->getParams().frequency) > (SRATE / 2)) {
|
||||
if (demod->getFrequency() != data_in->frequency
|
||||
&& abs(data_in->frequency - demod->getFrequency()) > (SRATE / 2)) {
|
||||
continue;
|
||||
}
|
||||
activeDemods++;
|
||||
@ -165,8 +164,8 @@ void SDRPostThread::threadMain() {
|
||||
DemodulatorInstance *demod = *i;
|
||||
DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod;
|
||||
|
||||
if (demod->getParams().frequency != data_in->frequency
|
||||
&& abs(data_in->frequency - demod->getParams().frequency) > (SRATE / 2)) {
|
||||
if (demod->getFrequency() != data_in->frequency
|
||||
&& abs(data_in->frequency - demod->getFrequency()) > (SRATE / 2)) {
|
||||
if (demod->isActive()) {
|
||||
demod->setActive(false);
|
||||
DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData;
|
||||
|
1596
src/util/DataTree.cpp
Executable file
1596
src/util/DataTree.cpp
Executable file
File diff suppressed because it is too large
Load Diff
357
src/util/DataTree.h
Executable file
357
src/util/DataTree.h
Executable file
@ -0,0 +1,357 @@
|
||||
#pragma once
|
||||
/*
|
||||
* DataElement/DataNode/DataTree -- structured serialization/deserialization system
|
||||
* designed for the CoolMule project :)
|
||||
*
|
||||
Copyright (C) 2003 by Charles J. Cliffe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define USE_FASTLZ 0
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <iostream>
|
||||
#include "tinyxml.h"
|
||||
|
||||
#if USE_FASTLZ
|
||||
#include "fastlz.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
/* type defines */
|
||||
#define DATA_NULL 0
|
||||
#define DATA_CHAR 1
|
||||
#define DATA_UCHAR 2
|
||||
#define DATA_INT 3
|
||||
#define DATA_UINT 4
|
||||
#define DATA_LONG 5
|
||||
#define DATA_ULONG 6
|
||||
#define DATA_LONGLONG 7
|
||||
#define DATA_FLOAT 8
|
||||
#define DATA_DOUBLE 9
|
||||
#define DATA_LONGDOUBLE 10
|
||||
#define DATA_STRING 11
|
||||
#define DATA_STR_VECTOR 12
|
||||
#define DATA_CHAR_VECTOR 13
|
||||
#define DATA_UCHAR_VECTOR 14
|
||||
#define DATA_INT_VECTOR 15
|
||||
#define DATA_UINT_VECTOR 16
|
||||
#define DATA_LONG_VECTOR 17
|
||||
#define DATA_ULONG_VECTOR 18
|
||||
#define DATA_LONGLONG_VECTOR 19
|
||||
#define DATA_FLOAT_VECTOR 20
|
||||
#define DATA_DOUBLE_VECTOR 21
|
||||
#define DATA_LONGDOUBLE_VECTOR 22
|
||||
#define DATA_VOID 23
|
||||
|
||||
|
||||
/* map comparison function */
|
||||
struct string_less : public std::binary_function<std::string,std::string,bool>
|
||||
{
|
||||
bool operator()(const std::string& a,const std::string& b) const
|
||||
{
|
||||
return a.compare(b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* int comparison function */
|
||||
struct int_less : public std::binary_function<int,int,bool>
|
||||
{
|
||||
bool operator()(int a,int b) const
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Data Exceptions */
|
||||
class DataException
|
||||
{
|
||||
private:
|
||||
string reason;
|
||||
|
||||
public:
|
||||
DataException(const char *why) : reason(why) {}
|
||||
string what() { return reason; }
|
||||
operator string() { return reason; }
|
||||
};
|
||||
|
||||
|
||||
class DataTypeMismatchException : public DataException
|
||||
{
|
||||
public:
|
||||
DataTypeMismatchException(const char *why) : DataException(why) { }
|
||||
};
|
||||
|
||||
|
||||
class DataInvalidChildException : public DataException
|
||||
{
|
||||
public:
|
||||
DataInvalidChildException(const char *why) : DataException(why) { }
|
||||
};
|
||||
|
||||
|
||||
class DataElement
|
||||
{
|
||||
private:
|
||||
int data_type;
|
||||
long data_size;
|
||||
int unit_size;
|
||||
|
||||
char *data_val;
|
||||
|
||||
void data_init(long data_size_in);
|
||||
|
||||
public:
|
||||
DataElement();
|
||||
~DataElement();
|
||||
|
||||
int getDataType();
|
||||
char *getDataPointer();
|
||||
long getDataSize();
|
||||
int getUnitSize();
|
||||
|
||||
/* set overloads */
|
||||
void set(const char &char_in);
|
||||
void set(const unsigned char &uchar_in);
|
||||
void set(const int &int_in);
|
||||
void set(const unsigned int &uint_in);
|
||||
void set(const long &long_in);
|
||||
void set(const unsigned long &ulong_in);
|
||||
void set(const long long &llong_in);
|
||||
void set(const float &float_in);
|
||||
void set(const double &double_in);
|
||||
void set(const long double &ldouble_in);
|
||||
|
||||
void set(const char *data_in, long size_in); /* voids, file chunks anyone? */
|
||||
void set(const char *data_in); /* strings, stops at NULL, returns as string */
|
||||
|
||||
void set(const string &str_in);
|
||||
|
||||
void set(vector<string> &strvect_in);
|
||||
void set(std::set<string> &strset_in);
|
||||
void set(vector<char> &charvect_in);
|
||||
void set(vector<unsigned char> &ucharvect_in);
|
||||
void set(vector<int> &intvect_in);
|
||||
void set(vector<unsigned int> &uintvect_in);
|
||||
void set(vector<long> &longvect_in);
|
||||
void set(vector<unsigned long> &ulongvect_in);
|
||||
void set(vector<long long> &llongvect_in);
|
||||
void set(vector<float> &floatvect_in);
|
||||
void set(vector<double> &doublevect_in);
|
||||
void set(vector<long double> &ldoublevect_in);
|
||||
|
||||
|
||||
/* get overloads */
|
||||
void get(char &char_in) throw (DataTypeMismatchException);
|
||||
void get(unsigned char &uchar_in) throw (DataTypeMismatchException);
|
||||
void get(int &int_in) throw (DataTypeMismatchException);
|
||||
void get(unsigned int &uint_in) throw (DataTypeMismatchException);
|
||||
void get(long &long_in) throw (DataTypeMismatchException);
|
||||
void get(unsigned long &ulong_in) throw (DataTypeMismatchException);
|
||||
void get(long long &long_in) throw (DataTypeMismatchException);
|
||||
void get(float &float_in) throw (DataTypeMismatchException);
|
||||
void get(double &double_in) throw (DataTypeMismatchException);
|
||||
void get(long double &ldouble_in) throw (DataTypeMismatchException);
|
||||
|
||||
void get(char **data_in) throw (DataTypeMismatchException); /* getting a void or string */
|
||||
void get(string &str_in) throw (DataTypeMismatchException);
|
||||
void get(std::set<string> &strset_in) throw (DataTypeMismatchException);
|
||||
|
||||
void get(vector<string> &strvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<char> &charvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<unsigned char> &ucharvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<int> &intvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<unsigned int> &uintvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<long> &longvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<unsigned long> &ulongvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<long long> &llongvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<float> &floatvect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<double> &doublevect_in) throw (DataTypeMismatchException);
|
||||
void get(vector<long double> &ldoublevect_in) throw (DataTypeMismatchException);
|
||||
|
||||
|
||||
/* special get functions, saves creating unnecessary vars */
|
||||
int getChar() throw (DataTypeMismatchException) { char i_get; get(i_get); return i_get; };
|
||||
unsigned int getUChar() throw (DataTypeMismatchException) { unsigned char i_get; get(i_get); return i_get; };
|
||||
int getInt() throw (DataTypeMismatchException) { int i_get; get(i_get); return i_get; };
|
||||
unsigned int getUInt() throw (DataTypeMismatchException) { unsigned int i_get; get(i_get); return i_get; };
|
||||
long getLong() throw (DataTypeMismatchException) { long l_get; get(l_get); return l_get; };
|
||||
unsigned long getULong() throw (DataTypeMismatchException) { unsigned long l_get; get(l_get); return l_get; };
|
||||
long getLongLong() throw (DataTypeMismatchException) { long long l_get; get(l_get); return l_get; };
|
||||
float getFloat() throw (DataTypeMismatchException) { float f_get; get(f_get); return f_get; };
|
||||
double getDouble() throw (DataTypeMismatchException) { double d_get; get(d_get); return d_get; };
|
||||
long double getLongDouble() throw (DataTypeMismatchException) { long double d_get; get(d_get); return d_get; };
|
||||
|
||||
|
||||
/* serialize functions */
|
||||
long getSerializedSize();
|
||||
long getSerialized(char **ser_str);
|
||||
|
||||
void setSerialized(char *ser_str);
|
||||
};
|
||||
|
||||
|
||||
class DataNode
|
||||
{
|
||||
private:
|
||||
DataNode *parentNode;
|
||||
vector<DataNode *> children;
|
||||
map<string, vector<DataNode *>, string_less> childmap;
|
||||
map<string, unsigned int, string_less> childmap_ptr;
|
||||
|
||||
string node_name;
|
||||
DataElement *data_elem;
|
||||
unsigned int ptr;
|
||||
|
||||
|
||||
public:
|
||||
DataNode();
|
||||
DataNode(const char *name_in);
|
||||
|
||||
~DataNode();
|
||||
|
||||
void setName(const char *name_in);
|
||||
string &getName() { return node_name; }
|
||||
|
||||
DataNode *getParentNode() { return parentNode; };
|
||||
void setParentNode(DataNode &parentNode_in) { parentNode = &parentNode_in; };
|
||||
|
||||
int numChildren(); /* Number of children */
|
||||
int numChildren(const char *name_in); /* Number of children named 'name_in' */
|
||||
|
||||
DataElement *element(); /* DataElement at this node */
|
||||
|
||||
DataNode *newChild(const char *name_in);
|
||||
DataNode *child(const char *name_in, int index = 0) throw (DataInvalidChildException);
|
||||
DataNode *child(int index) throw (DataInvalidChildException);
|
||||
|
||||
|
||||
bool hasAnother(const char *name_in); /* useful for while() loops in conjunction with getNext() */
|
||||
bool hasAnother();
|
||||
DataNode *getNext(const char *name_in) throw (DataInvalidChildException); /* get next of specified name */
|
||||
DataNode *getNext() throw (DataInvalidChildException); /* get next child */
|
||||
void rewind(const char *name_in); /* rewind specific */
|
||||
void rewind(); /* rewind generic */
|
||||
|
||||
void findAll(const char *name_in, vector<DataNode *> &node_list_out);
|
||||
|
||||
// operator string () { string s; element()->get(s); return s; }
|
||||
operator const char * () { if (element()->getDataType() == DATA_STRING) return element()->getDataPointer(); else return NULL; }
|
||||
operator char () { char v; element()->get(v); return v; }
|
||||
operator unsigned char () { unsigned char v; element()->get(v); return v; }
|
||||
operator int () { int v; element()->get(v); return v; }
|
||||
operator unsigned int () { unsigned int v; element()->get(v); return v; }
|
||||
operator long () { long v; element()->get(v); return v; }
|
||||
operator unsigned long () { unsigned long v; element()->get(v); return v; }
|
||||
operator long long () { long long v; element()->get(v); return v; }
|
||||
operator float () { float v; element()->get(v); return v; }
|
||||
operator double () { double v; element()->get(v); return v; }
|
||||
operator long double () { long double v; element()->get(v); return v; }
|
||||
|
||||
operator vector<char> () { vector<char> v; element()->get(v); return v; }
|
||||
operator vector<unsigned char> () { vector<unsigned char> v; element()->get(v); return v; }
|
||||
operator vector<int> () { vector<int> v; element()->get(v); return v; }
|
||||
operator vector<unsigned int> () { vector<unsigned int> v; element()->get(v); return v; }
|
||||
operator vector<long> () { vector<long> v; element()->get(v); return v; }
|
||||
operator vector<unsigned long> () { vector<unsigned long> v; element()->get(v); return v; }
|
||||
operator vector<float> () { vector<float> v; element()->get(v); return v; }
|
||||
operator vector<double> () { vector<double> v; element()->get(v); return v; }
|
||||
operator vector<long double> () { vector<long double> v; element()->get(v); return v; }
|
||||
|
||||
const string &operator= (const string &s) { element()->set(s); return s; }
|
||||
|
||||
char operator= (char i) { element()->set(i); return i; }
|
||||
unsigned char operator= (unsigned char i) { element()->set(i); return i; }
|
||||
int operator= (int i) { element()->set(i); return i; }
|
||||
unsigned int operator= (unsigned int i) { element()->set(i); return i; }
|
||||
long operator= (long i) { element()->set(i); return i; }
|
||||
unsigned long operator= (unsigned long i) { element()->set(i); return i; }
|
||||
long long operator= (long long i) { element()->set(i); return i; }
|
||||
float operator= (float i) { element()->set(i); return i; }
|
||||
double operator= (double i) { element()->set(i); return i; }
|
||||
long double operator= (long double i) { element()->set(i); return i; }
|
||||
|
||||
vector<char> &operator= (vector<char> &v) { element()->set(v); return v; }
|
||||
vector<unsigned char> &operator= (vector<unsigned char> &v) { element()->set(v); return v; }
|
||||
vector<int> &operator= (vector<int> &v) { element()->set(v); return v; }
|
||||
vector<unsigned int> &operator= (vector<unsigned int> &v) { element()->set(v); return v; }
|
||||
vector<long> &operator= (vector<long> &v) { element()->set(v); return v; }
|
||||
vector<unsigned long> &operator= (vector<unsigned long> &v) { element()->set(v); return v; }
|
||||
vector<float> &operator= (vector<float> &v) { element()->set(v); return v; }
|
||||
vector<double> &operator= (vector<double> &v) { element()->set(v); return v; }
|
||||
vector<long double> &operator= (vector<long double> &v) { element()->set(v); return v; }
|
||||
|
||||
DataNode *operator[] (const char *name_in) { return getNext(name_in); }
|
||||
DataNode *operator[] (int idx) { return child(idx); }
|
||||
|
||||
bool operator() (const char *name_in) { return hasAnother(name_in); }
|
||||
bool operator() () { return hasAnother(); }
|
||||
|
||||
DataNode *operator ^(const char *name_in) { return newChild(name_in); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef vector<DataNode *> DataNodeList;
|
||||
|
||||
enum DT_FloatingPointPolicy {
|
||||
USE_FLOAT,
|
||||
USE_DOUBLE
|
||||
};
|
||||
|
||||
class DataTree
|
||||
{
|
||||
private:
|
||||
DataNode dn_root;
|
||||
|
||||
public:
|
||||
DataTree(const char *name_in);
|
||||
DataTree();
|
||||
~DataTree();
|
||||
|
||||
DataNode *rootNode();
|
||||
|
||||
void nodeToXML(DataNode *elem, TiXmlElement *elxml);
|
||||
void setFromXML(DataNode *elem, TiXmlNode *elxml, bool root_node=true, DT_FloatingPointPolicy fpp=USE_FLOAT);
|
||||
void decodeXMLText(DataNode *elem, const char *in_text, DT_FloatingPointPolicy fpp);
|
||||
|
||||
void printXML(); /* print datatree as XML */
|
||||
long getSerializedSize(DataElement &de_node_names, bool debug=false); /* get serialized size + return node names header */
|
||||
long getSerialized(char **ser_str, bool debug=false);
|
||||
void setSerialized(char *ser_str, bool debug=false);
|
||||
|
||||
bool LoadFromFileXML(const std::string& filename, DT_FloatingPointPolicy fpp=USE_FLOAT);
|
||||
bool SaveToFileXML(const std::string& filename);
|
||||
|
||||
// bool SaveToFile(const std::string& filename);
|
||||
// bool LoadFromFile(const std::string& filename);
|
||||
|
||||
bool SaveToFile(const std::string& filename, bool compress = true, int compress_level = 2);
|
||||
bool LoadFromFile(const std::string& filename);
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ EVT_ENTER_WINDOW(TuningCanvas::OnMouseEnterWindow)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
TuningCanvas::TuningCanvas(wxWindow *parent, int *attribList) :
|
||||
InteractiveCanvas(parent, attribList), dragAccum(0) {
|
||||
InteractiveCanvas(parent, attribList), dragAccum(0) {
|
||||
|
||||
glContext = new TuningContext(this, &wxGetApp().GetContext(this));
|
||||
}
|
||||
@ -51,49 +51,56 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
glContext->DrawDemodFreqBw(0, 0, wxGetApp().getFrequency());
|
||||
}
|
||||
|
||||
if (mouseTracker.mouseDown()) {
|
||||
glContext->Draw(0.2, 0.2, 0.9, 0.6, mouseTracker.getOriginMouseX(), mouseTracker.getMouseX());
|
||||
}
|
||||
|
||||
glContext->DrawEnd();
|
||||
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
void TuningCanvas::OnIdle(wxIdleEvent &event) {
|
||||
if (mouseTracker.mouseDown()) {
|
||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||
|
||||
dragAccum += mouseTracker.getMouseX() - mouseTracker.getOriginMouseX();
|
||||
|
||||
if (uxDown > 0.275) {
|
||||
wxGetApp().setFrequency(wxGetApp().getFrequency() + (int) (mouseTracker.getOriginDeltaMouseX() * SRATE * 15.0));
|
||||
}
|
||||
|
||||
if (abs(dragAccum * 10.0) >= 1) {
|
||||
if (uxDown < -0.275 && activeDemod != NULL) {
|
||||
activeDemod->setFrequency(activeDemod->getFrequency() + (int) (dragAccum * 10.0));
|
||||
} else if (activeDemod != NULL) {
|
||||
activeDemod->setBandwidth(activeDemod->getBandwidth() + (int) (dragAccum * 10.0));
|
||||
}
|
||||
|
||||
while (dragAccum * 10.0 >= 1.0) {
|
||||
dragAccum -= 1.0 / 10.0;
|
||||
}
|
||||
while (dragAccum * -10.0 <= -1.0) {
|
||||
dragAccum += 1.0 / 10.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
void TuningCanvas::OnMouseMoved(wxMouseEvent& event) {
|
||||
InteractiveCanvas::OnMouseMoved(event);
|
||||
|
||||
if (mouseTracker.mouseDown()) {
|
||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||
|
||||
float uxPos = 2.0 * (mouseTracker.getMouseX() - 0.5);
|
||||
|
||||
dragAccum += mouseTracker.getDeltaMouseX();
|
||||
|
||||
if (uxPos < -0.275 && activeDemod != NULL) {
|
||||
if (abs(dragAccum * 100.0) >= 1) {
|
||||
activeDemod->setFrequency(activeDemod->getFrequency() + (int) (dragAccum * 100.0));
|
||||
dragAccum = 0;
|
||||
}
|
||||
} else if (uxPos > 0.275) {
|
||||
wxGetApp().setFrequency(wxGetApp().getFrequency() + (int) (mouseTracker.getDeltaMouseX() * SRATE * 100.0));
|
||||
dragAccum = 0;
|
||||
} else if (activeDemod != NULL) {
|
||||
if (abs(dragAccum * 100.0) >= 1) {
|
||||
activeDemod->setBandwidth(activeDemod->getBandwidth() + (int) (dragAccum * 100.0));
|
||||
dragAccum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TuningCanvas::OnMouseDown(wxMouseEvent& event) {
|
||||
InteractiveCanvas::OnMouseDown(event);
|
||||
mouseTracker.setHorizDragLock(true);
|
||||
mouseTracker.setVertDragLock(true);
|
||||
|
||||
uxDown = 2.0 * (mouseTracker.getMouseX() - 0.5);
|
||||
|
||||
dragAccum = 0;
|
||||
SetCursor(wxCURSOR_IBEAM);
|
||||
SetCursor (wxCURSOR_IBEAM);
|
||||
}
|
||||
|
||||
void TuningCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
||||
@ -102,19 +109,18 @@ void TuningCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
||||
|
||||
void TuningCanvas::OnMouseReleased(wxMouseEvent& event) {
|
||||
InteractiveCanvas::OnMouseReleased(event);
|
||||
mouseTracker.setHorizDragLock(false);
|
||||
mouseTracker.setVertDragLock(false);
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
SetCursor (wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
||||
void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
|
||||
InteractiveCanvas::OnMouseLeftWindow(event);
|
||||
SetCursor(wxCURSOR_CROSS);
|
||||
SetCursor (wxCURSOR_CROSS);
|
||||
}
|
||||
|
||||
void TuningCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
|
||||
InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event);
|
||||
SetCursor(wxCURSOR_SIZEWE);
|
||||
SetCursor (wxCURSOR_SIZEWE);
|
||||
}
|
||||
|
||||
void TuningCanvas::setHelpTip(std::string tip) {
|
||||
|
@ -35,6 +35,7 @@ private:
|
||||
|
||||
std::string helpTip;
|
||||
float dragAccum;
|
||||
float uxDown;
|
||||
//
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
@ -34,15 +34,15 @@ void TuningContext::DrawBegin() {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void TuningContext::Draw(float r, float g, float b, float a, float level) {
|
||||
void TuningContext::Draw(float r, float g, float b, float a, float p1, float p2) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
glColor4f(r, g, b, a);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(1.0, -1.0 + 2.0 * level);
|
||||
glVertex2f(-1.0, -1.0 + 2.0 * level);
|
||||
glVertex2f(-1.0, -1.0);
|
||||
glVertex2f(1.0, -1.0);
|
||||
glVertex2f(-1.0+p2*2.0, 1.0);
|
||||
glVertex2f(-1.0+p1*2.0, 1.0);
|
||||
glVertex2f(-1.0+p1*2.0, -1.0);
|
||||
glVertex2f(-1.0+p2*2.0, -1.0);
|
||||
glEnd();
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
@ -69,6 +69,8 @@ void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long c
|
||||
fontHeight = 12;
|
||||
}
|
||||
|
||||
glColor3f(0.85, 0.85, 0.85);
|
||||
|
||||
getFont(fontSize).drawString("Freq: ", -0.75, 0, fontHeight, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||
if (bw) {
|
||||
freqStr.str("");
|
||||
@ -78,11 +80,6 @@ void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long c
|
||||
}
|
||||
getFont(fontSize).drawString(freqStr.str(), -0.75, 0, fontHeight, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER);
|
||||
|
||||
glColor3f(0.65, 0.65, 0.65);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(-0.275, -1.0);
|
||||
glVertex2f(-0.275, 1.0);
|
||||
glEnd();
|
||||
|
||||
getFont(fontSize).drawString("BW: ", -0.10, 0, fontHeight, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||
if (bw) {
|
||||
@ -93,11 +90,6 @@ void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long c
|
||||
}
|
||||
getFont(fontSize).drawString(freqStr.str(), -0.10, 0, fontHeight, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER);
|
||||
|
||||
glColor3f(0.65, 0.65, 0.65);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(0.275, -1.0);
|
||||
glVertex2f(0.275, 1.0);
|
||||
glEnd();
|
||||
|
||||
getFont(fontSize).drawString("CTR: ", 0.50, 0, fontHeight, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||
if (center) {
|
||||
@ -107,5 +99,15 @@ void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long c
|
||||
freqStr.str("---");
|
||||
}
|
||||
getFont(fontSize).drawString(freqStr.str(), 0.50, 0, fontHeight, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER);
|
||||
|
||||
|
||||
glColor3f(0.65, 0.65, 0.65);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(-0.275, -1.0);
|
||||
glVertex2f(-0.275, 1.0);
|
||||
glVertex2f(0.275, -1.0);
|
||||
glVertex2f(0.275, 1.0);
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ public:
|
||||
TuningContext(TuningCanvas *canvas, wxGLContext *sharedContext);
|
||||
|
||||
void DrawBegin();
|
||||
void Draw(float r, float g, float b, float a, float level);
|
||||
void Draw(float r, float g, float b, float a, float p1, float p2);
|
||||
void DrawDemodFreqBw(long long freq, unsigned int bw, long long center);
|
||||
void DrawEnd();
|
||||
|
||||
|
@ -30,6 +30,7 @@ EVT_RIGHT_DOWN(WaterfallCanvas::OnMouseRightDown)
|
||||
EVT_RIGHT_UP(WaterfallCanvas::OnMouseRightReleased)
|
||||
EVT_LEAVE_WINDOW(WaterfallCanvas::OnMouseLeftWindow)
|
||||
EVT_ENTER_WINDOW(WaterfallCanvas::OnMouseEnterWindow)
|
||||
EVT_MOUSEWHEEL(WaterfallCanvas::OnMouseWheelMoved)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
||||
@ -302,6 +303,9 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
|
||||
if (mouseZoom != 1) {
|
||||
currentZoom = mouseZoom;
|
||||
mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2;
|
||||
if (fabs(mouseZoom-1.0)<0.01) {
|
||||
mouseZoom = 1;
|
||||
}
|
||||
}
|
||||
|
||||
long long bw;
|
||||
@ -674,6 +678,13 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) {
|
||||
|
||||
void WaterfallCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
||||
InteractiveCanvas::OnMouseWheelMoved(event);
|
||||
float movement = (float)event.GetWheelRotation() / (float)event.GetLinesPerAction();
|
||||
|
||||
#ifdef __APPLE__
|
||||
mouseZoom = 1.0f - movement/100.0f;
|
||||
#else
|
||||
mouseZoom = 1.0f - movement/1000.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user