kopia lustrzana https://github.com/jamescoxon/dl-fldigi
Use std::bind if available
rodzic
d3849ae877
commit
0dc1e2357e
|
@ -1,6 +1,8 @@
|
|||
Change Log:
|
||||
|
||||
2.08 1) Use PortAudio's C API; the C++ bindings are no longer required
|
||||
2) Boost is no longer required when std::(tr1::)bind is available, as is
|
||||
the case with g++ >= 4.0
|
||||
|
||||
2.07 1) bug fix for mode changes via SysV interface (pskmail / flarq)
|
||||
2) bug fix for modem configuration post quick change from status
|
||||
|
|
8
INSTALL
8
INSTALL
|
@ -3,10 +3,12 @@ Installation Instructions for fldigi
|
|||
|
||||
To compile fldigi you will need:
|
||||
|
||||
* version 1.1.x of the Fast Light Tool Kit (FLTK), with its
|
||||
development libraries and headers, and
|
||||
* A recent C++ compiler. The GNU C++ compilers in the 4.x series are
|
||||
known to work. Building with g++ 3.x requires the development files
|
||||
for the Boost C++ library.
|
||||
|
||||
* the development files for the Boost C++ library.
|
||||
* Version 1.1.x of the Fast Light Tool Kit (FLTK), with its
|
||||
development libraries and headers.
|
||||
|
||||
You should also install the libraries and headers for PortAudio, the
|
||||
Portable audio I/O library. It is possible, but not recommended, to
|
||||
|
|
58
configure.ac
58
configure.ac
|
@ -110,11 +110,43 @@ fi
|
|||
|
||||
|
||||
###########################
|
||||
# Boost
|
||||
# bind
|
||||
###########################
|
||||
AX_BOOST_BASE(1.32.0)
|
||||
if test "x$want_boost" = "xno"; then
|
||||
AC_MSG_ERROR([Boost is required])
|
||||
# Look for a working std::bind or std::tr1::bind. If neither is present
|
||||
# we will need Boost >= 1.32.0, which provides boost::bind.
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_MSG_CHECKING([for std::bind in <functional>])
|
||||
AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include <functional>
|
||||
void f(void) { }]],
|
||||
[[std::bind(f)();]])],
|
||||
[ac_cv_std_bind=yes], [ac_cv_std_bind=no] )
|
||||
AC_MSG_RESULT([$ac_cv_std_bind])
|
||||
if test "x$ac_cv_std_bind" = "xyes"; then
|
||||
AC_DEFINE(HAVE_STD_BIND, 1, [Define to 1 if we have std::bind in <functional>])
|
||||
else
|
||||
AC_DEFINE(HAVE_STD_BIND, 0, [Define to 1 if we have std::bind in <functional>])
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_std_bind" = "xno"; then
|
||||
AC_MSG_CHECKING([for std::tr1::bind in <tr1/functional>])
|
||||
AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include <tr1/functional>
|
||||
void f(void) { }]],
|
||||
[[std::tr1::bind(f)();]])],
|
||||
[ac_cv_std_tr1_bind=yes], [ac_cv_std_tr1_bind=no] )
|
||||
AC_MSG_RESULT([$ac_cv_std_tr1_bind])
|
||||
if test "x$ac_cv_std_tr1_bind" = "xyes"; then
|
||||
AC_DEFINE(HAVE_STD_TR1_BIND, 1, [Define to 1 if we have std::tr1::bind in <tr1/functional>])
|
||||
else
|
||||
AC_DEFINE(HAVE_STD_TR1_BIND, 0, [Define to 1 if we have std::tr1::bind in <tr1/functional>])
|
||||
fi
|
||||
fi
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
if test "x$ac_cv_std_bind" = "xno" && test "x$ac_cv_std_tr1_bind" = "xno"; then
|
||||
AX_BOOST_BASE(1.32.0)
|
||||
if test "x$want_boost" = "xno"; then
|
||||
AC_MSG_ERROR([Boost is required])
|
||||
fi
|
||||
fi
|
||||
|
||||
###########################
|
||||
|
@ -178,22 +210,22 @@ AC_ARG_WITH([sndfile],
|
|||
esac],
|
||||
[ac_cv_want_sndfile=check])
|
||||
if test "x$ac_cv_want_sndfile" = "xno"; then
|
||||
AC_DEFINE(USE_SNDFILE, 0, [Set to 1 if we are using sndfile, 0 otherwise])
|
||||
AC_DEFINE(USE_SNDFILE, 0, [Define to 1 if we are using sndfile])
|
||||
ac_cv_sndfile=no
|
||||
else
|
||||
PKG_CHECK_EXISTS(sndfile >= 1.0.10, ac_cv_sndfile=yes, ac_cv_sndfile=no)
|
||||
if test "x$ac_cv_want_sndfile" = "xcheck"; then
|
||||
PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.10, [:], [:])
|
||||
if test "x$ac_cv_sndfile" = "xyes"; then
|
||||
AC_DEFINE(USE_SNDFILE, 1, [Set to 1 if we are using sndfile, 0 otherwise])
|
||||
AC_DEFINE(USE_SNDFILE, 1, [Define to 1 if we are using sndfile])
|
||||
else
|
||||
AC_DEFINE(USE_SNDFILE, 0, [Set to 1 if we are using sndfile, 0 otherwise])
|
||||
AC_DEFINE(USE_SNDFILE, 0, [Define to 1 if we are using sndfile])
|
||||
fi
|
||||
else # $ac_cv_want_sndfile is yes
|
||||
if test "x$ac_cv_sndfile" = "xno"; then
|
||||
AC_MSG_NOTICE([--with-sndfile was given, but test for sndfile failed])
|
||||
else
|
||||
AC_DEFINE(USE_SNDFILE, 1, [Set to 1 if we are using sndfile, 0 otherwise])
|
||||
AC_DEFINE(USE_SNDFILE, 1, [Define to 1 if we are using sndfile])
|
||||
fi
|
||||
PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.10) # for the error message
|
||||
fi
|
||||
|
@ -216,13 +248,13 @@ AC_ARG_WITH([portaudio],
|
|||
if test "x$ac_cv_want_portaudio" = "xyes"; then
|
||||
PKG_CHECK_EXISTS(portaudio-2.0 >= 19, ac_cv_portaudio=yes, ac_cv_portaudio=no)
|
||||
if test "x$ac_cv_portaudio" = "xyes"; then
|
||||
AC_DEFINE(USE_PORTAUDIO, 1, [Set to 1 if we are using PortAudio, 0 otherwise])
|
||||
AC_DEFINE(USE_PORTAUDIO, 1, [Define to 1 if we are using PortAudio])
|
||||
else
|
||||
AC_MSG_NOTICE([portaudio test failed (use --without-portaudio to disable)])
|
||||
fi
|
||||
PKG_CHECK_MODULES(PORTAUDIO, portaudio-2.0 >= 19)
|
||||
else
|
||||
AC_DEFINE(USE_PORTAUDIO, 0, [Set to 1 if we are using PortAudio, 0 otherwise])
|
||||
AC_DEFINE(USE_PORTAUDIO, 0, [Define to 1 if we are using PortAudio])
|
||||
ac_cv_portaudio=no
|
||||
fi
|
||||
AC_SUBST([PORTAUDIO_CFLAGS])
|
||||
|
@ -248,15 +280,15 @@ else
|
|||
if test "x$ac_cv_want_hamlib" = "xcheck"; then
|
||||
PKG_CHECK_MODULES(HAMLIB, hamlib >= 1.2.0, [:], [:])
|
||||
if test "x$ac_cv_hamlib" = "xyes"; then
|
||||
AC_DEFINE(USE_HAMLIB, 1, [Set to 1 if we are using hamlib, 0 otherwise])
|
||||
AC_DEFINE(USE_HAMLIB, 1, [Define to 1 if we are using hamlib])
|
||||
else
|
||||
AC_DEFINE(USE_HAMLIB, 0, [Set to 1 if we are using hamlib, 0 otherwise])
|
||||
AC_DEFINE(USE_HAMLIB, 0, [Define to 1 if we are using hamlib])
|
||||
fi
|
||||
else # $ac_cv_want_hamlib is yes
|
||||
if test "x$ac_cv_hamlib" = "xno"; then
|
||||
AC_MSG_NOTICE([--with-hamlib was given, but test for hamlib failed])
|
||||
else
|
||||
AC_DEFINE(USE_HAMLIB, 1, [Set to 1 if we are using hamlib, 0 otherwise])
|
||||
AC_DEFINE(USE_HAMLIB, 1, [Define to 1 if we are using hamlib])
|
||||
fi
|
||||
PKG_CHECK_MODULES(HAMLIB, hamlib >= 1.2.0) # for the error message
|
||||
fi
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
AC_DEFUN([AX_BOOST_BASE],
|
||||
[
|
||||
AC_ARG_WITH([boost],
|
||||
AS_HELP_STRING([--with-boost=DIR], [specify the root directory for boost]),
|
||||
AS_HELP_STRING([--with-boost=DIR], [specify the root directory for boost @<:@autodetect@:>@]),
|
||||
[
|
||||
if test "$withval" = "no"; then
|
||||
want_boost="no"
|
||||
|
|
|
@ -7,7 +7,7 @@ AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include -I$(srcdir)/irrxml @BOOST_CPPFLAGS
|
|||
|
||||
AM_CXXFLAGS = @FLTK_CFLAGS@ @PORTAUDIO_CFLAGS@ @SNDFILE_CFLAGS@ \
|
||||
@SAMPLERATE_CFLAGS@ @HAMLIB_CFLAGS@ \
|
||||
-pipe -Wall -O2 -ffast-math -fno-rtti -fexceptions -finline-functions
|
||||
-pipe -Wall -O2 -ffast-math -fexceptions -finline-functions
|
||||
AM_CFLAGS = $(AM_CXXFLAGS)
|
||||
|
||||
LDADD = @BOOST_LDFLAGS@ @FLTK_LIBS@ @PORTAUDIO_LIBS@ @SNDFILE_LIBS@ \
|
||||
|
|
|
@ -1202,7 +1202,7 @@ void put_Bandwidth(int bandwidth)
|
|||
void display_metric(double metric)
|
||||
{
|
||||
FL_LOCK_D();
|
||||
QUEUE(CMP_CB(&Fl_Progress::value, pgrsSquelch, metric)); //pgrsSquelch->value(metric);
|
||||
QUEUE(CMP_CB(static_cast<void (Fl_Progress::*)(float)>(&Fl_Progress::value), pgrsSquelch, metric)); //pgrsSquelch->value(metric);
|
||||
FL_UNLOCK_D();
|
||||
FL_AWAKE_D();
|
||||
}
|
||||
|
@ -1213,8 +1213,8 @@ void put_cwRcvWPM(double wpm)
|
|||
int L = progdefaults.CWlowerlimit;
|
||||
double dWPM = 100.0*(wpm - L)/(U - L);
|
||||
FL_LOCK_D();
|
||||
QUEUE(CMP_CB(&Fl_Progress::value, prgsCWrcvWPM, dWPM)); //prgsCWrcvWPM->value(dWPM);
|
||||
QUEUE(CMP_CB(&Fl_Value_Output::value, valCWrcvWPM, (int)wpm)); //valCWrcvWPM->value((int)wpm);
|
||||
QUEUE(CMP_CB(static_cast<void (Fl_Progress::*)(float)>(&Fl_Progress::value), prgsCWrcvWPM, dWPM)); //prgsCWrcvWPM->value(dWPM);
|
||||
QUEUE(CMP_CB(static_cast<int (Fl_Value_Output::*)(double)>(&Fl_Value_Output::value), valCWrcvWPM, (int)wpm)); //valCWrcvWPM->value((int)wpm);
|
||||
FL_UNLOCK_D();
|
||||
FL_AWAKE_D();
|
||||
}
|
||||
|
@ -1295,7 +1295,7 @@ void put_sec_char( char chr )
|
|||
if (strSecText.length() > 60)
|
||||
strSecText.erase(0,1);
|
||||
FL_LOCK_D();
|
||||
QUEUE(CMP_CB(&Fl_Box::label, StatusBar, strSecText.c_str())); //StatusBar->label(strSecText.c_str());
|
||||
QUEUE(CMP_CB(static_cast<void (Fl_Box::*)(const char *)>(&Fl_Box::label), StatusBar, strSecText.c_str())); //StatusBar->label(strSecText.c_str());
|
||||
FL_UNLOCK_D();
|
||||
FL_AWAKE_D();
|
||||
}
|
||||
|
@ -1313,7 +1313,7 @@ void put_status(const char *msg, double timeout)
|
|||
m[sizeof(m) - 1] = '\0';
|
||||
|
||||
FL_LOCK_D();
|
||||
QUEUE(CMP_CB(&Fl_Box::label, StatusBar, m)); // StatusBar->label(m);
|
||||
QUEUE(CMP_CB(static_cast<void (Fl_Box::*)(const char *)>(&Fl_Box::label), StatusBar, m)); // StatusBar->label(m);
|
||||
// While it is safe to call to use Fl::add_timeout without qrunner
|
||||
// regardless of our caller's context, queuing ensures that clear_status_cb
|
||||
// really gets called at least ``timeout'' seconds after the label is set.
|
||||
|
@ -1332,7 +1332,7 @@ void put_Status2(const char *msg)
|
|||
m[sizeof(m) - 1] = '\0';
|
||||
|
||||
FL_LOCK_D();
|
||||
QUEUE(CMP_CB(&Fl_Box::label, Status2, m)); //Status2->label(m);
|
||||
QUEUE(CMP_CB(static_cast<void (Fl_Box::*)(const char *)>(&Fl_Box::label), Status2, m)); //Status2->label(m);
|
||||
FL_UNLOCK_D();
|
||||
FL_AWAKE_D();
|
||||
}
|
||||
|
@ -1344,7 +1344,7 @@ void put_Status1(const char *msg)
|
|||
m[sizeof(m) - 1] = '\0';
|
||||
|
||||
FL_LOCK_D();
|
||||
QUEUE(CMP_CB(&Fl_Box::label, Status1, m)); //Status1->label(m);
|
||||
QUEUE(CMP_CB(static_cast<void (Fl_Box::*)(const char *)>(&Fl_Box::label), Status1, m)); //Status1->label(m);
|
||||
FL_UNLOCK_D();
|
||||
FL_AWAKE_D();
|
||||
}
|
||||
|
@ -1387,7 +1387,7 @@ void clear_StatusMessages()
|
|||
void put_MODEstatus(trx_mode mode)
|
||||
{
|
||||
FL_LOCK_D();
|
||||
QUEUE(CMP_CB(&Fl_Button::label, MODEstatus, mode_info[mode].sname)); //MODEstatus->label(mode_names[mode]);
|
||||
QUEUE(CMP_CB(static_cast<void (Fl_Button::*)(const char *)>(&Fl_Button::label), MODEstatus, mode_info[mode].sname)); //MODEstatus->label(mode_names[mode]);
|
||||
FL_UNLOCK_D();
|
||||
FL_AWAKE_D();
|
||||
}
|
||||
|
|
|
@ -24,14 +24,23 @@
|
|||
#define QRUNNER_H_
|
||||
|
||||
#ifndef NDEBUG
|
||||
# include <iostream>
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/protect.hpp>
|
||||
|
||||
#if HAVE_STD_BIND
|
||||
# include <functional>
|
||||
using std::bind;
|
||||
#elif HAVE_STD_TR1_BIND
|
||||
# include <tr1/functional>
|
||||
using std::tr1::bind;
|
||||
#else
|
||||
# include <boost/bind.hpp>
|
||||
using boost::bind;
|
||||
#endif
|
||||
|
||||
#include "threads.h"
|
||||
#include "qrunner/fqueue.h"
|
||||
|
@ -48,66 +57,24 @@ private:
|
|||
std::string msg;
|
||||
};
|
||||
|
||||
struct signal_after
|
||||
struct fsignal
|
||||
{
|
||||
typedef void result_type;
|
||||
Fl_Mutex *m;
|
||||
Fl_Cond *c;
|
||||
|
||||
signal_after(Fl_Mutex *m_, Fl_Cond *c_) : m(m_), c(c_) { }
|
||||
template <typename F>
|
||||
void operator()(const F& f) const
|
||||
fsignal(Fl_Mutex *m_, Fl_Cond *c_) : m(m_), c(c_) { }
|
||||
void operator()(void) const
|
||||
{
|
||||
f();
|
||||
fl_lock(m);
|
||||
fl_cond_signal(c);
|
||||
fl_unlock(m);
|
||||
}
|
||||
};
|
||||
|
||||
struct deadline
|
||||
{
|
||||
struct timespec dl;
|
||||
|
||||
deadline(const struct timespec &dl_) : dl(dl_) { }
|
||||
template <typename F>
|
||||
void operator()(const F& f) const
|
||||
{
|
||||
struct timespec now;
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) == -1)
|
||||
throw qexception(errno);
|
||||
|
||||
if (dl > now)
|
||||
f();
|
||||
#ifndef NDEBUG
|
||||
else
|
||||
std::cerr << "too late for event\n";
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
struct timer
|
||||
{
|
||||
struct timespec t;
|
||||
|
||||
timer(const struct timespec &t_) : t(t_) { }
|
||||
template <typename F>
|
||||
void operator()(const F& f) const
|
||||
{
|
||||
struct timespec now;
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) == -1)
|
||||
throw qexception(errno);
|
||||
|
||||
struct timespec diff = now - t;
|
||||
std::cout << "t: " << (double)diff.tv_sec + diff.tv_nsec/1e9 << '\n';
|
||||
|
||||
f();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct nop
|
||||
{
|
||||
typedef void result_type;
|
||||
void operator()(void) const { }
|
||||
};
|
||||
|
||||
|
@ -146,13 +113,17 @@ public:
|
|||
if (!attached)
|
||||
return request(f, pri);
|
||||
|
||||
for (;;) {
|
||||
if (request(f, pri))
|
||||
break;
|
||||
sched_yield();
|
||||
}
|
||||
Fl_Mutex m = PTHREAD_MUTEX_INITIALIZER;
|
||||
Fl_Cond c = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
fsignal s(&m, &c);
|
||||
fl_lock(&m);
|
||||
signal_after sa(&m, &c);
|
||||
for (;;) {
|
||||
if (request(boost::bind<void>(sa, f), pri))
|
||||
if (request(s, pri))
|
||||
break;
|
||||
sched_yield();
|
||||
}
|
||||
|
@ -162,30 +133,6 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
bool request_dl(const F &f, double dtime, size_t pri = 0)
|
||||
{
|
||||
struct timespec now, dl;
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) == -1)
|
||||
throw qexception(errno);
|
||||
dl = now + dtime;
|
||||
|
||||
deadline d(dl);
|
||||
return request(boost::bind<void>(d, f), pri);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template <typename F>
|
||||
bool request_time(const F &f, size_t pri = 0)
|
||||
{
|
||||
struct timespec now;
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) == -1)
|
||||
throw qexception(errno);
|
||||
timer t(now);
|
||||
return request(boost::bind<void>(t, f), pri);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void execute(int fd, void *arg);
|
||||
void flush(void);
|
||||
|
||||
|
@ -211,29 +158,19 @@ extern qrunner *cbq[NUM_QRUNNER_THREADS];
|
|||
#define QUEUE_ASYNC(...) \
|
||||
do { \
|
||||
if (GET_THREAD_ID() != FLMAIN_TID) \
|
||||
cbq[GET_THREAD_ID()]->request(boost::bind(__VA_ARGS__)); \
|
||||
cbq[GET_THREAD_ID()]->request(bind(__VA_ARGS__)); \
|
||||
else \
|
||||
boost::bind(__VA_ARGS__)(); \
|
||||
bind(__VA_ARGS__)(); \
|
||||
} while (0)
|
||||
|
||||
#define QUEUE_SYNC(...) \
|
||||
do { \
|
||||
if (GET_THREAD_ID() != FLMAIN_TID) \
|
||||
cbq[GET_THREAD_ID()]->request_sync(boost::protect(boost::bind(__VA_ARGS__))); \
|
||||
cbq[GET_THREAD_ID()]->request_sync(bind(__VA_ARGS__)); \
|
||||
else \
|
||||
boost::bind(__VA_ARGS__)(); \
|
||||
bind(__VA_ARGS__)(); \
|
||||
} while (0)
|
||||
|
||||
#define QUEUE_DL(d_, ...) \
|
||||
do { \
|
||||
if (GET_THREAD_ID() != FLMAIN_TID) \
|
||||
cbq[GET_THREAD_ID()]->request_dl(boost::protect(boost::bind(__VA_ARGS__)), d_); \
|
||||
else \
|
||||
boost::bind(__VA_ARGS__)(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
#define QUEUE_FLUSH() \
|
||||
do { \
|
||||
if (GET_THREAD_ID() != FLMAIN_TID) \
|
||||
|
|
Ładowanie…
Reference in New Issue