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/Timer.cpp
|
||||||
src/util/MouseTracker.cpp
|
src/util/MouseTracker.cpp
|
||||||
src/util/GLFont.cpp
|
src/util/GLFont.cpp
|
||||||
|
src/util/DataTree.cpp
|
||||||
src/visual/PrimaryGLContext.cpp
|
src/visual/PrimaryGLContext.cpp
|
||||||
src/visual/InteractiveCanvas.cpp
|
src/visual/InteractiveCanvas.cpp
|
||||||
src/visual/MeterCanvas.cpp
|
src/visual/MeterCanvas.cpp
|
||||||
@ -151,6 +152,10 @@ SET (cubicsdr_sources
|
|||||||
src/visual/WaterfallContext.cpp
|
src/visual/WaterfallContext.cpp
|
||||||
external/rtaudio/RtAudio.cpp
|
external/rtaudio/RtAudio.cpp
|
||||||
external/lodepng/lodepng.cpp
|
external/lodepng/lodepng.cpp
|
||||||
|
external/tinyxml/tinyxml.cpp
|
||||||
|
external/tinyxml/tinystr.cpp
|
||||||
|
external/tinyxml/tinyxmlparser.cpp
|
||||||
|
external/tinyxml/tinyxmlerror.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
SET (cubicsdr_headers
|
SET (cubicsdr_headers
|
||||||
@ -171,6 +176,7 @@ SET (cubicsdr_headers
|
|||||||
src/util/ThreadQueue.h
|
src/util/ThreadQueue.h
|
||||||
src/util/MouseTracker.h
|
src/util/MouseTracker.h
|
||||||
src/util/GLFont.h
|
src/util/GLFont.h
|
||||||
|
src/util/DataTree.h
|
||||||
src/visual/PrimaryGLContext.h
|
src/visual/PrimaryGLContext.h
|
||||||
src/visual/InteractiveCanvas.h
|
src/visual/InteractiveCanvas.h
|
||||||
src/visual/MeterCanvas.h
|
src/visual/MeterCanvas.h
|
||||||
@ -187,6 +193,8 @@ SET (cubicsdr_headers
|
|||||||
src/visual/WaterfallContext.h
|
src/visual/WaterfallContext.h
|
||||||
external/rtaudio/RtAudio.h
|
external/rtaudio/RtAudio.h
|
||||||
external/lodepng/lodepng.h
|
external/lodepng/lodepng.h
|
||||||
|
external/tinyxml/tinyxml.h
|
||||||
|
external/tinyxml/tinystr.h
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories (
|
include_directories (
|
||||||
@ -198,6 +206,8 @@ include_directories (
|
|||||||
${PROJECT_SOURCE_DIR}/src
|
${PROJECT_SOURCE_DIR}/src
|
||||||
${PROJECT_SOURCE_DIR}/external/rtaudio
|
${PROJECT_SOURCE_DIR}/external/rtaudio
|
||||||
${PROJECT_SOURCE_DIR}/external/lodepng
|
${PROJECT_SOURCE_DIR}/external/lodepng
|
||||||
|
${PROJECT_SOURCE_DIR}/external/fastlz
|
||||||
|
${PROJECT_SOURCE_DIR}/external/tinyxml
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_DEFINITIONS(
|
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
|
#endif
|
||||||
|
|
||||||
#include "wx/numdlg.h"
|
#include "wx/numdlg.h"
|
||||||
|
#include "wx/filedlg.h"
|
||||||
|
|
||||||
#if !wxUSE_GLCANVAS
|
#if !wxUSE_GLCANVAS
|
||||||
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
||||||
@ -17,6 +18,7 @@
|
|||||||
#include "DemodulatorMgr.h"
|
#include "DemodulatorMgr.h"
|
||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include "CubicSDR.h"
|
#include "CubicSDR.h"
|
||||||
|
#include "DataTree.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@ -26,13 +28,12 @@ wxBEGIN_EVENT_TABLE(AppFrame, wxFrame)
|
|||||||
//EVT_MENU(wxID_NEW, AppFrame::OnNewWindow)
|
//EVT_MENU(wxID_NEW, AppFrame::OnNewWindow)
|
||||||
EVT_MENU(wxID_CLOSE, AppFrame::OnClose)
|
EVT_MENU(wxID_CLOSE, AppFrame::OnClose)
|
||||||
EVT_MENU(wxID_ANY, AppFrame::OnMenu)
|
EVT_MENU(wxID_ANY, AppFrame::OnMenu)
|
||||||
|
|
||||||
EVT_COMMAND(wxID_ANY, wxEVT_THREAD, AppFrame::OnThread)
|
EVT_COMMAND(wxID_ANY, wxEVT_THREAD, AppFrame::OnThread)
|
||||||
EVT_IDLE(AppFrame::OnIdle)
|
EVT_IDLE(AppFrame::OnIdle)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
AppFrame::AppFrame() :
|
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 *vbox = new wxBoxSizer(wxVERTICAL);
|
||||||
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
|
||||||
@ -40,12 +41,12 @@ AppFrame::AppFrame() :
|
|||||||
wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer *demodTray = new wxBoxSizer(wxHORIZONTAL);
|
||||||
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
|
|
||||||
demodModeSelector = new ModeSelectorCanvas(this, NULL);
|
demodModeSelector = new ModeSelectorCanvas(this, NULL);
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_FM,"FM");
|
demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_AM,"AM");
|
demodModeSelector->addChoice(DEMOD_TYPE_AM, "AM");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_LSB,"LSB");
|
demodModeSelector->addChoice(DEMOD_TYPE_LSB, "LSB");
|
||||||
demodModeSelector->addChoice(DEMOD_TYPE_USB,"USB");
|
demodModeSelector->addChoice(DEMOD_TYPE_USB, "USB");
|
||||||
|
demodModeSelector->addChoice(DEMOD_TYPE_DSB, "DSB");
|
||||||
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
|
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
|
||||||
|
|
||||||
// demodTray->AddSpacer(2);
|
// demodTray->AddSpacer(2);
|
||||||
@ -110,7 +111,11 @@ AppFrame::AppFrame() :
|
|||||||
wxMenu *menu = new wxMenu;
|
wxMenu *menu = new wxMenu;
|
||||||
// menu->Append(wxID_NEW);
|
// menu->Append(wxID_NEW);
|
||||||
menu->Append(wxID_SET_FREQ_OFFSET, "Set Frequency Offset");
|
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->AppendSeparator();
|
||||||
|
menu->Append(wxID_RESET, "&Reset Session");
|
||||||
menu->Append(wxID_CLOSE);
|
menu->Append(wxID_CLOSE);
|
||||||
|
|
||||||
menuBar->Append(menu, wxT("&File"));
|
menuBar->Append(menu, wxT("&File"));
|
||||||
@ -155,6 +160,14 @@ AppFrame::AppFrame() :
|
|||||||
|
|
||||||
GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), DEFAULT_FREQ));
|
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 };
|
// static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
|
||||||
// wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
|
// wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
|
||||||
// ShowFullScreen(true);
|
// ShowFullScreen(true);
|
||||||
@ -171,15 +184,44 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
|||||||
activeDemodulator = NULL;
|
activeDemodulator = NULL;
|
||||||
}
|
}
|
||||||
} else if (event.GetId() == wxID_SET_FREQ_OFFSET) {
|
} 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) {
|
if (ofs != -1) {
|
||||||
wxGetApp().setOffset(ofs);
|
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)) {
|
void AppFrame::OnClose(wxCommandEvent& WXUNUSED(event)) {
|
||||||
Close(true);
|
Close(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
|
void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
|
||||||
@ -281,3 +323,117 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
event.Skip();
|
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_RT_AUDIO_DEVICE 1000
|
||||||
#define wxID_SET_FREQ_OFFSET 2001
|
#define wxID_SET_FREQ_OFFSET 2001
|
||||||
|
#define wxID_RESET 2002
|
||||||
|
|
||||||
// Define a new frame type
|
// Define a new frame type
|
||||||
class AppFrame: public wxFrame {
|
class AppFrame: public wxFrame {
|
||||||
@ -23,6 +24,9 @@ public:
|
|||||||
void OnThread(wxCommandEvent& event);
|
void OnThread(wxCommandEvent& event);
|
||||||
void OnEventInput(wxThreadEvent& event);
|
void OnEventInput(wxThreadEvent& event);
|
||||||
|
|
||||||
|
void saveSession(std::string fileName);
|
||||||
|
bool loadSession(std::string fileName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnMenu(wxCommandEvent& event);
|
void OnMenu(wxCommandEvent& event);
|
||||||
void OnClose(wxCommandEvent& event);
|
void OnClose(wxCommandEvent& event);
|
||||||
@ -46,5 +50,7 @@ private:
|
|||||||
std::map<int,RtAudio::DeviceInfo> outputDevices;
|
std::map<int,RtAudio::DeviceInfo> outputDevices;
|
||||||
std::map<int,wxMenuItem *> outputDeviceMenuItems;
|
std::map<int,wxMenuItem *> outputDeviceMenuItems;
|
||||||
|
|
||||||
|
std::string currentSessionFile;
|
||||||
|
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define CUBICSDR_VERSION "v0.01a"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#define BUF_SIZE (16384*2)
|
#define BUF_SIZE (16384*2)
|
||||||
#define SRATE 2000000
|
#define SRATE 2000000
|
||||||
@ -9,8 +11,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define DEFAULT_FFT_SIZE 2048
|
#define DEFAULT_FFT_SIZE 2048
|
||||||
|
|
||||||
//#define DEFAULT_FREQ 98900000
|
#define DEFAULT_FREQ 100000000
|
||||||
#define DEFAULT_FREQ 132000000
|
|
||||||
#define AUDIO_FREQUENCY 44100
|
#define AUDIO_FREQUENCY 44100
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -10,8 +10,8 @@ std::map<int, std::thread *> AudioThread::deviceThread;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
|
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
|
||||||
currentInput(NULL), inputQueue(inputQueue), audioQueuePtr(0), underflowCount(0), terminated(false), active(false), outputDevice(-1), gain(1.0), threadQueueNotify(
|
currentInput(NULL), inputQueue(inputQueue), audioQueuePtr(0), underflowCount(0), terminated(false), active(false), outputDevice(-1), gain(
|
||||||
threadQueueNotify) {
|
1.0), threadQueueNotify(threadQueueNotify) {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
boundThreads = new std::vector<AudioThread *>;
|
boundThreads = new std::vector<AudioThread *>;
|
||||||
#endif
|
#endif
|
||||||
@ -72,6 +72,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||||
|
if (srcmix->terminated) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
srcmix->audioQueuePtr = 0;
|
srcmix->audioQueuePtr = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -88,6 +91,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||||
|
if (srcmix->terminated) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
srcmix->audioQueuePtr = 0;
|
srcmix->audioQueuePtr = 0;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -104,6 +110,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||||
|
if (srcmix->terminated) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
srcmix->audioQueuePtr = 0;
|
srcmix->audioQueuePtr = 0;
|
||||||
}
|
}
|
||||||
if (srcmix->currentInput && srcmix->currentInput->data.size()) {
|
if (srcmix->currentInput && srcmix->currentInput->data.size()) {
|
||||||
@ -124,6 +133,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
srcmix->inputQueue->pop(srcmix->currentInput);
|
srcmix->inputQueue->pop(srcmix->currentInput);
|
||||||
|
if (srcmix->terminated) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
srcmix->audioQueuePtr = 0;
|
srcmix->audioQueuePtr = 0;
|
||||||
}
|
}
|
||||||
if (srcmix->currentInput && srcmix->currentInput->data.size()) {
|
if (srcmix->currentInput && srcmix->currentInput->data.size()) {
|
||||||
@ -151,6 +163,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
|
|
||||||
if (!src->currentInput) {
|
if (!src->currentInput) {
|
||||||
src->inputQueue->pop(src->currentInput);
|
src->inputQueue->pop(src->currentInput);
|
||||||
|
if (src->terminated) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
src->audioQueuePtr = 0;
|
src->audioQueuePtr = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -167,6 +182,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
src->inputQueue->pop(src->currentInput);
|
src->inputQueue->pop(src->currentInput);
|
||||||
|
if (src->terminated) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
src->audioQueuePtr = 0;
|
src->audioQueuePtr = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -183,6 +201,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
src->inputQueue->pop(src->currentInput);
|
src->inputQueue->pop(src->currentInput);
|
||||||
|
if (src->terminated) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
src->audioQueuePtr = 0;
|
src->audioQueuePtr = 0;
|
||||||
}
|
}
|
||||||
if (src->currentInput && src->currentInput->data.size()) {
|
if (src->currentInput && src->currentInput->data.size()) {
|
||||||
@ -201,6 +222,9 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
src->inputQueue->pop(src->currentInput);
|
src->inputQueue->pop(src->currentInput);
|
||||||
|
if (src->terminated) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
src->audioQueuePtr = 0;
|
src->audioQueuePtr = 0;
|
||||||
}
|
}
|
||||||
if (src->currentInput && src->currentInput->data.size()) {
|
if (src->currentInput && src->currentInput->data.size()) {
|
||||||
@ -344,10 +368,12 @@ void AudioThread::threadMain() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupDevice((outputDevice.load() == -1)?(dac.getDefaultOutputDevice()):outputDevice.load());
|
setupDevice((outputDevice.load() == -1) ? (dac.getDefaultOutputDevice()) : outputDevice.load());
|
||||||
|
|
||||||
std::cout << "Audio thread started." << std::endl;
|
std::cout << "Audio thread started." << std::endl;
|
||||||
|
|
||||||
|
terminated = false;
|
||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
AudioThreadCommand command;
|
AudioThreadCommand command;
|
||||||
cmdQueue.pop(command);
|
cmdQueue.pop(command);
|
||||||
@ -357,29 +383,35 @@ void AudioThread::threadMain() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioThreadInput dummy;
|
||||||
|
inputQueue->push(&dummy);
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (deviceController[parameters.deviceId] != this) {
|
if (deviceController[parameters.deviceId] != this) {
|
||||||
deviceController[parameters.deviceId]->removeThread(this);
|
deviceController[parameters.deviceId]->removeThread(this);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dac.stopStream();
|
if (dac.isStreamOpen()) {
|
||||||
dac.closeStream();
|
if (dac.isStreamRunning()) {
|
||||||
|
dac.stopStream();
|
||||||
|
}
|
||||||
|
dac.closeStream();
|
||||||
|
}
|
||||||
} catch (RtAudioError& e) {
|
} catch (RtAudioError& e) {
|
||||||
e.printMessage();
|
e.printMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
// Stop the stream
|
if (dac.isStreamOpen()) {
|
||||||
dac.stopStream();
|
if (dac.isStreamRunning()) {
|
||||||
dac.closeStream();
|
dac.stopStream();
|
||||||
|
}
|
||||||
|
dac.closeStream();
|
||||||
|
}
|
||||||
} catch (RtAudioError& e) {
|
} catch (RtAudioError& e) {
|
||||||
e.printMessage();
|
e.printMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dac.isStreamOpen()) {
|
|
||||||
dac.closeStream();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::cout << "Audio thread done." << std::endl;
|
std::cout << "Audio thread done." << std::endl;
|
||||||
@ -425,7 +457,6 @@ void AudioThread::setActive(bool state) {
|
|||||||
active = state;
|
active = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AudioThreadCommandQueue *AudioThread::getCommandQueue() {
|
AudioThreadCommandQueue *AudioThread::getCommandQueue() {
|
||||||
return &cmdQueue;
|
return &cmdQueue;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
std::atomic<unsigned int> audioQueuePtr;
|
std::atomic<unsigned int> audioQueuePtr;
|
||||||
std::atomic<unsigned int> underflowCount;
|
std::atomic<unsigned int> underflowCount;
|
||||||
std::atomic<bool> terminated;
|
std::atomic<bool> terminated;
|
||||||
|
std::atomic<bool> initialized;
|
||||||
std::atomic<bool> active;
|
std::atomic<bool> active;
|
||||||
std::atomic<int> outputDevice;
|
std::atomic<int> outputDevice;
|
||||||
float gain;
|
float gain;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#define DEMOD_TYPE_AM 2
|
#define DEMOD_TYPE_AM 2
|
||||||
#define DEMOD_TYPE_LSB 3
|
#define DEMOD_TYPE_LSB 3
|
||||||
#define DEMOD_TYPE_USB 4
|
#define DEMOD_TYPE_USB 4
|
||||||
|
#define DEMOD_TYPE_DSB 5
|
||||||
|
|
||||||
|
|
||||||
class DemodulatorThread;
|
class DemodulatorThread;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "DemodulatorInstance.h"
|
#include "DemodulatorInstance.h"
|
||||||
|
|
||||||
DemodulatorInstance::DemodulatorInstance() :
|
DemodulatorInstance::DemodulatorInstance() :
|
||||||
t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(false), audioTerminated(false), demodTerminated(
|
t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(true), audioTerminated(true), demodTerminated(
|
||||||
false), preDemodTerminated(false), active(false), squelch(false), stereo(false), currentFrequency(0), currentBandwidth(0) {
|
true), preDemodTerminated(true), active(false), squelch(false), stereo(false), currentFrequency(0), currentBandwidth(0) {
|
||||||
|
|
||||||
label = new std::string("Unnamed");
|
label = new std::string("Unnamed");
|
||||||
threadQueueDemod = new DemodulatorThreadInputQueue;
|
threadQueueDemod = new DemodulatorThreadInputQueue;
|
||||||
@ -26,9 +26,13 @@ DemodulatorInstance::DemodulatorInstance() :
|
|||||||
DemodulatorInstance::~DemodulatorInstance() {
|
DemodulatorInstance::~DemodulatorInstance() {
|
||||||
delete audioThread;
|
delete audioThread;
|
||||||
delete demodulatorThread;
|
delete demodulatorThread;
|
||||||
|
delete demodulatorPreThread;
|
||||||
delete audioInputQueue;
|
|
||||||
delete threadQueueDemod;
|
delete threadQueueDemod;
|
||||||
|
delete threadQueuePostDemod;
|
||||||
|
delete threadQueueCommand;
|
||||||
|
delete threadQueueNotify;
|
||||||
|
delete threadQueueControl;
|
||||||
|
delete audioInputQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
|
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
|
||||||
@ -36,7 +40,16 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQu
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::run() {
|
void DemodulatorInstance::run() {
|
||||||
|
if (active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// while (!isTerminated()) {
|
||||||
|
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
// }
|
||||||
|
|
||||||
currentFrequency = demodulatorPreThread->getParams().frequency;
|
currentFrequency = demodulatorPreThread->getParams().frequency;
|
||||||
|
currentDemodType = demodulatorThread->getDemodulatorType();
|
||||||
|
|
||||||
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
|
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
|
||||||
|
|
||||||
@ -63,6 +76,8 @@ void DemodulatorInstance::run() {
|
|||||||
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
|
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
|
||||||
#endif
|
#endif
|
||||||
active = true;
|
active = true;
|
||||||
|
audioTerminated = demodTerminated = preDemodTerminated = terminated = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::updateLabel(long long freq) {
|
void DemodulatorInstance::updateLabel(long long freq) {
|
||||||
@ -109,12 +124,10 @@ bool DemodulatorInstance::isTerminated() {
|
|||||||
|
|
||||||
switch (cmd.cmd) {
|
switch (cmd.cmd) {
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED:
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED:
|
||||||
audioThread = NULL;
|
|
||||||
t_Audio->join();
|
t_Audio->join();
|
||||||
audioTerminated = true;
|
audioTerminated = true;
|
||||||
break;
|
break;
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED:
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED:
|
||||||
demodulatorThread = NULL;
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
pthread_join(t_Demod, NULL);
|
pthread_join(t_Demod, NULL);
|
||||||
#else
|
#else
|
||||||
@ -123,7 +136,6 @@ bool DemodulatorInstance::isTerminated() {
|
|||||||
demodTerminated = true;
|
demodTerminated = true;
|
||||||
break;
|
break;
|
||||||
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED:
|
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED:
|
||||||
demodulatorPreThread = NULL;
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
pthread_join(t_PreDemod, NULL);
|
pthread_join(t_PreDemod, NULL);
|
||||||
#else
|
#else
|
||||||
@ -146,8 +158,12 @@ bool DemodulatorInstance::isActive() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setActive(bool state) {
|
void DemodulatorInstance::setActive(bool state) {
|
||||||
|
if (active && !state) {
|
||||||
|
audioThread->setActive(state);
|
||||||
|
} else if (!active && state) {
|
||||||
|
audioThread->setActive(state);
|
||||||
|
}
|
||||||
active = state;
|
active = state;
|
||||||
audioThread->setActive(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DemodulatorInstance::isStereo() {
|
bool DemodulatorInstance::isStereo() {
|
||||||
@ -197,7 +213,9 @@ float DemodulatorInstance::getSquelchLevel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setOutputDevice(int device_id) {
|
void DemodulatorInstance::setOutputDevice(int device_id) {
|
||||||
if (audioThread) {
|
if (!active) {
|
||||||
|
audioThread->setInitOutputDevice(device_id);
|
||||||
|
} else if (audioThread) {
|
||||||
AudioThreadCommand command;
|
AudioThreadCommand command;
|
||||||
command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE;
|
command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE;
|
||||||
command.int_value = device_id;
|
command.int_value = device_id;
|
||||||
@ -216,7 +234,12 @@ void DemodulatorInstance::checkBandwidth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setDemodulatorType(int demod_type_in) {
|
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;
|
DemodulatorThreadControlCommand command;
|
||||||
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
|
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
|
||||||
currentDemodType = demod_type_in;
|
currentDemodType = demod_type_in;
|
||||||
@ -231,7 +254,11 @@ int DemodulatorInstance::getDemodulatorType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setBandwidth(int bw) {
|
void DemodulatorInstance::setBandwidth(int bw) {
|
||||||
if (demodulatorPreThread && threadQueueCommand) {
|
if (!active) {
|
||||||
|
currentBandwidth = bw;
|
||||||
|
checkBandwidth();
|
||||||
|
demodulatorPreThread->getParams().bandwidth = currentBandwidth;
|
||||||
|
} else if (demodulatorPreThread && threadQueueCommand) {
|
||||||
DemodulatorThreadCommand command;
|
DemodulatorThreadCommand command;
|
||||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
|
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
|
||||||
currentBandwidth = bw;
|
currentBandwidth = bw;
|
||||||
@ -239,7 +266,6 @@ void DemodulatorInstance::setBandwidth(int bw) {
|
|||||||
command.llong_value = currentBandwidth;
|
command.llong_value = currentBandwidth;
|
||||||
threadQueueCommand->push(command);
|
threadQueueCommand->push(command);
|
||||||
}
|
}
|
||||||
demodulatorPreThread->getParams().bandwidth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DemodulatorInstance::getBandwidth() {
|
int DemodulatorInstance::getBandwidth() {
|
||||||
@ -250,17 +276,20 @@ int DemodulatorInstance::getBandwidth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setFrequency(long long freq) {
|
void DemodulatorInstance::setFrequency(long long freq) {
|
||||||
if ((freq - getBandwidth()/2) <= 0) {
|
if ((freq - getBandwidth() / 2) <= 0) {
|
||||||
freq = getBandwidth()/2;
|
freq = getBandwidth() / 2;
|
||||||
}
|
}
|
||||||
if (demodulatorPreThread && threadQueueCommand) {
|
if (!active) {
|
||||||
DemodulatorThreadCommand command;
|
currentFrequency = freq;
|
||||||
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
|
demodulatorPreThread->getParams().frequency = currentFrequency;
|
||||||
currentFrequency = freq;
|
} else if (demodulatorPreThread && threadQueueCommand) {
|
||||||
command.llong_value = freq;
|
DemodulatorThreadCommand command;
|
||||||
threadQueueCommand->push(command);
|
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
|
||||||
}
|
currentFrequency = freq;
|
||||||
demodulatorPreThread->getParams().bandwidth;
|
command.llong_value = freq;
|
||||||
|
threadQueueCommand->push(command);
|
||||||
|
}
|
||||||
|
demodulatorPreThread->getParams().bandwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long DemodulatorInstance::getFrequency() {
|
long long DemodulatorInstance::getFrequency() {
|
||||||
|
@ -29,6 +29,7 @@ DemodulatorInstance *DemodulatorMgr::newThread() {
|
|||||||
void DemodulatorMgr::terminateAll() {
|
void DemodulatorMgr::terminateAll() {
|
||||||
while (demods.size()) {
|
while (demods.size()) {
|
||||||
DemodulatorInstance *d = demods.back();
|
DemodulatorInstance *d = demods.back();
|
||||||
|
wxGetApp().removeDemodulator(d);
|
||||||
deleteThread(d);
|
deleteThread(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,8 +55,8 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
|
|||||||
|
|
||||||
if (i != demods.end()) {
|
if (i != demods.end()) {
|
||||||
demods.erase(i);
|
demods.erase(i);
|
||||||
demod->terminate();
|
|
||||||
}
|
}
|
||||||
|
demod->terminate();
|
||||||
|
|
||||||
demods_deleted.push_back(demod);
|
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> in_buf_data;
|
||||||
std::vector<liquid_float_complex> out_buf_data;
|
std::vector<liquid_float_complex> out_buf_data;
|
||||||
|
|
||||||
|
terminated = false;
|
||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
DemodulatorThreadIQData *inp;
|
DemodulatorThreadIQData *inp;
|
||||||
iqInputQueue->pop(inp);
|
iqInputQueue->pop(inp);
|
||||||
|
@ -32,6 +32,10 @@ public:
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setParams(DemodulatorThreadParameters ¶ms_in) {
|
||||||
|
params = params_in;
|
||||||
|
}
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQue
|
|||||||
demodFM = freqdem_create(0.5);
|
demodFM = freqdem_create(0.5);
|
||||||
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
|
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_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_DSB_CSP = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
||||||
demodAM = demodAM_DSB_CSP;
|
demodAM = demodAM_DSB_CSP;
|
||||||
|
|
||||||
@ -91,6 +92,8 @@ void DemodulatorThread::threadMain() {
|
|||||||
|
|
||||||
std::cout << "Demodulator thread started.." << std::endl;
|
std::cout << "Demodulator thread started.." << std::endl;
|
||||||
|
|
||||||
|
terminated = false;
|
||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
DemodulatorThreadPostIQData *inp;
|
DemodulatorThreadPostIQData *inp;
|
||||||
iqInputQueue->pop(inp);
|
iqInputQueue->pop(inp);
|
||||||
@ -112,9 +115,9 @@ void DemodulatorThread::threadMain() {
|
|||||||
audioResampler = inp->audioResampler;
|
audioResampler = inp->audioResampler;
|
||||||
stereoResampler = inp->stereoResampler;
|
stereoResampler = inp->stereoResampler;
|
||||||
|
|
||||||
ampmodem_reset(demodAM_USB);
|
if (demodAM) {
|
||||||
ampmodem_reset(demodAM_LSB);
|
ampmodem_reset(demodAM);
|
||||||
ampmodem_reset(demodAM_DSB_CSP);
|
}
|
||||||
freqdem_reset(demodFM);
|
freqdem_reset(demodFM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +177,7 @@ void DemodulatorThread::threadMain() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DEMOD_TYPE_AM:
|
case DEMOD_TYPE_AM:
|
||||||
|
case DEMOD_TYPE_DSB:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,15 +354,23 @@ void DemodulatorThread::threadMain() {
|
|||||||
if (newDemodType != DEMOD_TYPE_NULL) {
|
if (newDemodType != DEMOD_TYPE_NULL) {
|
||||||
switch (newDemodType) {
|
switch (newDemodType) {
|
||||||
case DEMOD_TYPE_FM:
|
case DEMOD_TYPE_FM:
|
||||||
|
freqdem_reset(demodFM);
|
||||||
break;
|
break;
|
||||||
case DEMOD_TYPE_LSB:
|
case DEMOD_TYPE_LSB:
|
||||||
demodAM = demodAM_USB;
|
demodAM = demodAM_USB;
|
||||||
|
ampmodem_reset(demodAM);
|
||||||
break;
|
break;
|
||||||
case DEMOD_TYPE_USB:
|
case DEMOD_TYPE_USB:
|
||||||
demodAM = demodAM_LSB;
|
demodAM = demodAM_LSB;
|
||||||
|
ampmodem_reset(demodAM);
|
||||||
|
break;
|
||||||
|
case DEMOD_TYPE_DSB:
|
||||||
|
demodAM = demodAM_DSB;
|
||||||
|
ampmodem_reset(demodAM);
|
||||||
break;
|
break;
|
||||||
case DEMOD_TYPE_AM:
|
case DEMOD_TYPE_AM:
|
||||||
demodAM = demodAM_DSB_CSP;
|
demodAM = demodAM_DSB_CSP;
|
||||||
|
ampmodem_reset(demodAM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
demodulatorType = newDemodType;
|
demodulatorType = newDemodType;
|
||||||
|
@ -62,6 +62,7 @@ protected:
|
|||||||
freqdem demodFM;
|
freqdem demodFM;
|
||||||
ampmodem demodAM;
|
ampmodem demodAM;
|
||||||
ampmodem demodAM_DSB_CSP;
|
ampmodem demodAM_DSB_CSP;
|
||||||
|
ampmodem demodAM_DSB;
|
||||||
ampmodem demodAM_LSB;
|
ampmodem demodAM_LSB;
|
||||||
ampmodem demodAM_USB;
|
ampmodem demodAM_USB;
|
||||||
|
|
||||||
|
@ -130,9 +130,8 @@ void SDRPostThread::threadMain() {
|
|||||||
std::vector<DemodulatorInstance *>::iterator i;
|
std::vector<DemodulatorInstance *>::iterator i;
|
||||||
for (i = demodulators.begin(); i != demodulators.end(); i++) {
|
for (i = demodulators.begin(); i != demodulators.end(); i++) {
|
||||||
DemodulatorInstance *demod = *i;
|
DemodulatorInstance *demod = *i;
|
||||||
|
if (demod->getFrequency() != data_in->frequency
|
||||||
if (demod->getParams().frequency != data_in->frequency
|
&& abs(data_in->frequency - demod->getFrequency()) > (SRATE / 2)) {
|
||||||
&& abs(data_in->frequency - demod->getParams().frequency) > (SRATE / 2)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
activeDemods++;
|
activeDemods++;
|
||||||
@ -165,8 +164,8 @@ void SDRPostThread::threadMain() {
|
|||||||
DemodulatorInstance *demod = *i;
|
DemodulatorInstance *demod = *i;
|
||||||
DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod;
|
DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod;
|
||||||
|
|
||||||
if (demod->getParams().frequency != data_in->frequency
|
if (demod->getFrequency() != data_in->frequency
|
||||||
&& abs(data_in->frequency - demod->getParams().frequency) > (SRATE / 2)) {
|
&& abs(data_in->frequency - demod->getFrequency()) > (SRATE / 2)) {
|
||||||
if (demod->isActive()) {
|
if (demod->isActive()) {
|
||||||
demod->setActive(false);
|
demod->setActive(false);
|
||||||
DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData;
|
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()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
TuningCanvas::TuningCanvas(wxWindow *parent, int *attribList) :
|
TuningCanvas::TuningCanvas(wxWindow *parent, int *attribList) :
|
||||||
InteractiveCanvas(parent, attribList), dragAccum(0) {
|
InteractiveCanvas(parent, attribList), dragAccum(0) {
|
||||||
|
|
||||||
glContext = new TuningContext(this, &wxGetApp().GetContext(this));
|
glContext = new TuningContext(this, &wxGetApp().GetContext(this));
|
||||||
}
|
}
|
||||||
@ -51,49 +51,56 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
glContext->DrawDemodFreqBw(0, 0, wxGetApp().getFrequency());
|
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();
|
glContext->DrawEnd();
|
||||||
|
|
||||||
SwapBuffers();
|
SwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TuningCanvas::OnIdle(wxIdleEvent &event) {
|
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);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TuningCanvas::OnMouseMoved(wxMouseEvent& event) {
|
void TuningCanvas::OnMouseMoved(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseMoved(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) {
|
void TuningCanvas::OnMouseDown(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseDown(event);
|
InteractiveCanvas::OnMouseDown(event);
|
||||||
mouseTracker.setHorizDragLock(true);
|
|
||||||
mouseTracker.setVertDragLock(true);
|
mouseTracker.setVertDragLock(true);
|
||||||
|
|
||||||
|
uxDown = 2.0 * (mouseTracker.getMouseX() - 0.5);
|
||||||
|
|
||||||
dragAccum = 0;
|
dragAccum = 0;
|
||||||
SetCursor(wxCURSOR_IBEAM);
|
SetCursor (wxCURSOR_IBEAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TuningCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
void TuningCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
||||||
@ -102,19 +109,18 @@ void TuningCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
|||||||
|
|
||||||
void TuningCanvas::OnMouseReleased(wxMouseEvent& event) {
|
void TuningCanvas::OnMouseReleased(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseReleased(event);
|
InteractiveCanvas::OnMouseReleased(event);
|
||||||
mouseTracker.setHorizDragLock(false);
|
|
||||||
mouseTracker.setVertDragLock(false);
|
mouseTracker.setVertDragLock(false);
|
||||||
SetCursor(wxCURSOR_SIZEWE);
|
SetCursor (wxCURSOR_SIZEWE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
|
void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseLeftWindow(event);
|
InteractiveCanvas::OnMouseLeftWindow(event);
|
||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor (wxCURSOR_CROSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TuningCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
|
void TuningCanvas::OnMouseEnterWindow(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event);
|
InteractiveCanvas::mouseTracker.OnMouseEnterWindow(event);
|
||||||
SetCursor(wxCURSOR_SIZEWE);
|
SetCursor (wxCURSOR_SIZEWE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TuningCanvas::setHelpTip(std::string tip) {
|
void TuningCanvas::setHelpTip(std::string tip) {
|
||||||
|
@ -35,6 +35,7 @@ private:
|
|||||||
|
|
||||||
std::string helpTip;
|
std::string helpTip;
|
||||||
float dragAccum;
|
float dragAccum;
|
||||||
|
float uxDown;
|
||||||
//
|
//
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
@ -34,15 +34,15 @@ void TuningContext::DrawBegin() {
|
|||||||
glDisable(GL_TEXTURE_2D);
|
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);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
glColor4f(r, g, b, a);
|
glColor4f(r, g, b, a);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glVertex2f(1.0, -1.0 + 2.0 * level);
|
glVertex2f(-1.0+p2*2.0, 1.0);
|
||||||
glVertex2f(-1.0, -1.0 + 2.0 * level);
|
glVertex2f(-1.0+p1*2.0, 1.0);
|
||||||
glVertex2f(-1.0, -1.0);
|
glVertex2f(-1.0+p1*2.0, -1.0);
|
||||||
glVertex2f(1.0, -1.0);
|
glVertex2f(-1.0+p2*2.0, -1.0);
|
||||||
glEnd();
|
glEnd();
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
@ -69,6 +69,8 @@ void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long c
|
|||||||
fontHeight = 12;
|
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);
|
getFont(fontSize).drawString("Freq: ", -0.75, 0, fontHeight, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||||
if (bw) {
|
if (bw) {
|
||||||
freqStr.str("");
|
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);
|
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);
|
getFont(fontSize).drawString("BW: ", -0.10, 0, fontHeight, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||||
if (bw) {
|
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);
|
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);
|
getFont(fontSize).drawString("CTR: ", 0.50, 0, fontHeight, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
|
||||||
if (center) {
|
if (center) {
|
||||||
@ -107,5 +99,15 @@ void TuningContext::DrawDemodFreqBw(long long freq, unsigned int bw, long long c
|
|||||||
freqStr.str("---");
|
freqStr.str("---");
|
||||||
}
|
}
|
||||||
getFont(fontSize).drawString(freqStr.str(), 0.50, 0, fontHeight, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER);
|
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);
|
TuningContext(TuningCanvas *canvas, wxGLContext *sharedContext);
|
||||||
|
|
||||||
void DrawBegin();
|
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 DrawDemodFreqBw(long long freq, unsigned int bw, long long center);
|
||||||
void DrawEnd();
|
void DrawEnd();
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ EVT_RIGHT_DOWN(WaterfallCanvas::OnMouseRightDown)
|
|||||||
EVT_RIGHT_UP(WaterfallCanvas::OnMouseRightReleased)
|
EVT_RIGHT_UP(WaterfallCanvas::OnMouseRightReleased)
|
||||||
EVT_LEAVE_WINDOW(WaterfallCanvas::OnMouseLeftWindow)
|
EVT_LEAVE_WINDOW(WaterfallCanvas::OnMouseLeftWindow)
|
||||||
EVT_ENTER_WINDOW(WaterfallCanvas::OnMouseEnterWindow)
|
EVT_ENTER_WINDOW(WaterfallCanvas::OnMouseEnterWindow)
|
||||||
|
EVT_MOUSEWHEEL(WaterfallCanvas::OnMouseWheelMoved)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
||||||
@ -302,6 +303,9 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
|
|||||||
if (mouseZoom != 1) {
|
if (mouseZoom != 1) {
|
||||||
currentZoom = mouseZoom;
|
currentZoom = mouseZoom;
|
||||||
mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2;
|
mouseZoom = mouseZoom + (1.0 - mouseZoom) * 0.2;
|
||||||
|
if (fabs(mouseZoom-1.0)<0.01) {
|
||||||
|
mouseZoom = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long long bw;
|
long long bw;
|
||||||
@ -674,6 +678,13 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) {
|
|||||||
|
|
||||||
void WaterfallCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
void WaterfallCanvas::OnMouseWheelMoved(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseWheelMoved(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) {
|
void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user