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
	
	 Stelios Bounanos
						Stelios Bounanos