kopia lustrzana https://github.com/jamescoxon/dl-fldigi
guard lock
* Added guard lock class - impacts upon - xmlrpc class implementation - wefax implementation * This ensures that a mutex is always unlocked when leaving a function or blockpull/2/head
rodzic
c2ba559f1c
commit
50fa414165
|
@ -124,4 +124,28 @@ bool thread_in_list(int id, const int* list);
|
|||
|
||||
#include "fl_lock.h"
|
||||
|
||||
/// This ensures that a mutex is always unlocked when leaving a function or block.
|
||||
class guard_lock
|
||||
{
|
||||
public:
|
||||
guard_lock(pthread_mutex_t* m);
|
||||
~guard_lock(void);
|
||||
private:
|
||||
pthread_mutex_t* mutex;
|
||||
};
|
||||
|
||||
/// This wraps together a mutex and a condition variable which are used
|
||||
/// together very often for queues etc...
|
||||
class syncobj
|
||||
{
|
||||
pthread_mutex_t m_mutex ;
|
||||
pthread_cond_t m_cond ;
|
||||
public:
|
||||
syncobj();
|
||||
~syncobj();
|
||||
pthread_mutex_t * mtxp(void) { return & m_mutex; }
|
||||
void signal();
|
||||
bool wait( double seconds );
|
||||
};
|
||||
|
||||
#endif // !THREADS_H_
|
||||
|
|
|
@ -35,6 +35,8 @@ public:
|
|||
static void setpicture_link(wefax *me);
|
||||
static void save_image(const std::string & fil_name, const std::string & extra_comments);
|
||||
static void power( double start, double phase, double image, double black, double stop );
|
||||
static void send_image( const std::string & fil_name );
|
||||
static void restore_max_lines(void);
|
||||
};
|
||||
|
||||
#endif // _WEFAX_PIC_H
|
||||
|
|
|
@ -28,6 +28,11 @@ class wefax : public modem {
|
|||
|
||||
/// For updating the logbook when loading/saving an image file.
|
||||
cQsoRec m_qso_rec ;
|
||||
|
||||
/// Non-copiable object.
|
||||
wefax ();
|
||||
wefax ( const wefax & );
|
||||
wefax & operator=( const wefax & );
|
||||
public:
|
||||
wefax (trx_mode md);
|
||||
virtual ~wefax ();
|
||||
|
@ -103,6 +108,27 @@ public:
|
|||
{
|
||||
m_adif_log = the_flag ;
|
||||
}
|
||||
|
||||
/// Helper string indicating the internal state of the wefax engine.
|
||||
std::string state_string(void) const;
|
||||
|
||||
/// Maximum wait time when getting information about received and sent files.
|
||||
static const int max_delay = 3600 * 24 * 365 ;
|
||||
|
||||
/// Called by the engine when a file is received.
|
||||
void put_received_file(const std::string & filnam);
|
||||
|
||||
/// Used by XML-RPC to get the list of received files.
|
||||
std::string get_received_file(double max_seconds=max_delay);
|
||||
|
||||
/// Called by XML-RPC to send a file which resides on the machine where fldigi runs.
|
||||
std::string send_file( const std::string & filnam, double max_seconds=max_delay);
|
||||
|
||||
/// Called before sending a file. Transmitting is an exclusive process.
|
||||
bool transmit_lock_acquire( const std::string & filnam, double max_seconds=max_delay);
|
||||
|
||||
/// Called after sending a file so another sending can take place.
|
||||
void transmit_lock_release( const std::string & err_msg );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "threads.h"
|
||||
|
||||
THREAD_ID_TYPE thread_id_;
|
||||
|
@ -99,3 +101,50 @@ void linux_log_tid(void)
|
|||
LOG_DEBUG(PACKAGE_TARNAME " thread %" PRIdPTR " is LWP %ld", GET_THREAD_ID(), syscall(SYS_gettid));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Synchronization objects.
|
||||
|
||||
guard_lock::guard_lock(pthread_mutex_t* m) : mutex(m)
|
||||
{
|
||||
pthread_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
guard_lock::~guard_lock(void)
|
||||
{
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
syncobj::syncobj()
|
||||
{
|
||||
pthread_mutex_init( & m_mutex, NULL );
|
||||
pthread_cond_init( & m_cond, NULL );
|
||||
}
|
||||
|
||||
syncobj::~syncobj()
|
||||
{
|
||||
pthread_mutex_destroy( & m_mutex );
|
||||
pthread_cond_destroy( & m_cond );
|
||||
}
|
||||
|
||||
void syncobj::signal()
|
||||
{
|
||||
int rc = pthread_cond_signal( &m_cond );
|
||||
if( rc )
|
||||
{
|
||||
throw std::runtime_error(strerror(rc));
|
||||
}
|
||||
}
|
||||
|
||||
bool syncobj::wait( double seconds )
|
||||
{
|
||||
int rc = pthread_cond_timedwait_rel( &m_cond, &m_mutex, seconds );
|
||||
switch( rc )
|
||||
{
|
||||
case 0 : return true ;
|
||||
default : throw std::runtime_error(strerror(rc));
|
||||
case ETIMEDOUT: return false ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#include "waterfall.h"
|
||||
#include "macros.h"
|
||||
#include "qrunner.h"
|
||||
#include "wefax.h"
|
||||
#include "wefax-pic.h"
|
||||
|
||||
#if USE_HAMLIB
|
||||
#include "hamlib.h"
|
||||
|
@ -189,16 +191,8 @@ ostream& XML_RPC_Server::list_methods(ostream& out)
|
|||
|
||||
// =============================================================================
|
||||
// Methods that change the server state must call XMLRPC_LOCK
|
||||
|
||||
class xmlrpc_lock
|
||||
{
|
||||
public:
|
||||
xmlrpc_lock(pthread_mutex_t* m) : mutex(m) { pthread_mutex_lock(mutex); }
|
||||
~xmlrpc_lock(void) { pthread_mutex_unlock(mutex); }
|
||||
private:
|
||||
pthread_mutex_t* mutex;
|
||||
};
|
||||
#define XMLRPC_LOCK SET_THREAD_ID(XMLRPC_TID); xmlrpc_lock autolock_(server_mutex)
|
||||
// guard_lock (include/threads.h) ensures that mutex are always unlocked.
|
||||
#define XMLRPC_LOCK SET_THREAD_ID(XMLRPC_TID); guard_lock autolock_(server_mutex)
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
@ -2433,6 +2427,206 @@ public:
|
|||
|
||||
// =============================================================================
|
||||
|
||||
// Returns the current wefax modem pointer.
|
||||
static wefax * get_wefax(void)
|
||||
{
|
||||
if( ( active_modem->get_mode() >= MODE_WEFAX_FIRST )
|
||||
&& ( active_modem->get_mode() <= MODE_WEFAX_LAST ) )
|
||||
{
|
||||
wefax * ptr = dynamic_cast<wefax *>( active_modem );
|
||||
if( ptr == NULL ) throw runtime_error("Inconsistent wefax object");
|
||||
return ptr ;
|
||||
}
|
||||
throw runtime_error("Not in wefax mode");
|
||||
}
|
||||
|
||||
struct Wefax_state_string : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_state_string() {
|
||||
_signature = "s:n";
|
||||
_help = "Returns Wefax engine state (tx and rx) for information."; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( get_wefax()->state_string() );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what());
|
||||
}
|
||||
};
|
||||
|
||||
struct Wefax_skip_apt : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_skip_apt() {
|
||||
_signature = "s:n";
|
||||
_help = "Skip APT during Wefax reception"; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
get_wefax()->skip_apt();
|
||||
*retval = xmlrpc_c::value_string( "" );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
/// TODO: Refresh the screen with the new value.
|
||||
struct Wefax_skip_phasing : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_skip_phasing() {
|
||||
_signature = "s:n";
|
||||
_help = "Skip phasing during Wefax reception"; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
get_wefax()->skip_phasing(true);
|
||||
*retval = xmlrpc_c::value_string( "" );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: The image should be reloaded just like cancelling from the GUI.
|
||||
struct Wefax_set_tx_abort_flag : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_set_tx_abort_flag() {
|
||||
_signature = "s:n";
|
||||
_help = "Cancels Wefax image transmission"; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
get_wefax()->set_tx_abort_flag();
|
||||
*retval = xmlrpc_c::value_string( "" );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
struct Wefax_end_reception : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_end_reception() {
|
||||
_signature = "s:n";
|
||||
_help = "End Wefax image reception"; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
get_wefax()->end_reception();
|
||||
*retval = xmlrpc_c::value_string( "" );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
struct Wefax_start_manual_reception : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_start_manual_reception() {
|
||||
_signature = "s:n";
|
||||
_help = "Starts fax image reception in manual mode"; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
get_wefax()->set_rx_manual_mode(true);
|
||||
get_wefax()->skip_apt();
|
||||
get_wefax()->skip_phasing(true);
|
||||
*retval = xmlrpc_c::value_string( "" );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
struct Wefax_set_adif_log : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_set_adif_log() {
|
||||
_signature = "s:b";
|
||||
_help = "Set/reset logging to received/transmit images to ADIF log file"; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
get_wefax()->set_adif_log( params.getBoolean(0));
|
||||
*retval = xmlrpc_c::value_string( "" );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
struct Wefax_set_max_lines : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_set_max_lines() {
|
||||
_signature = "s:i";
|
||||
_help = "Set maximum lines for fax image reception"; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
get_wefax()->set_max_lines( params.getInt(0));
|
||||
/// This updates the GUI.
|
||||
REQ( wefax_pic::restore_max_lines );
|
||||
*retval = xmlrpc_c::value_string( "" );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
struct Wefax_get_received_file : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_get_received_file() {
|
||||
_signature = "s:i";
|
||||
_help = "Waits for next received fax file, returns its name with a delay. Empty string if timeout."; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
std::string filename = get_wefax()->get_received_file( params.getInt(0));
|
||||
*retval = xmlrpc_c::value_string( filename );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
struct Wefax_send_file : public xmlrpc_c::method
|
||||
{
|
||||
Wefax_send_file() {
|
||||
_signature = "s:si";
|
||||
_help = "Send file. returns an empty string if OK otherwise an error message."; }
|
||||
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
try
|
||||
{
|
||||
std::string status = get_wefax()->send_file( params.getString(0), params.getInt(1) );
|
||||
*retval = xmlrpc_c::value_string( status );
|
||||
}
|
||||
catch( const exception & e )
|
||||
{
|
||||
*retval = xmlrpc_c::value_string( e.what() );
|
||||
}
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
|
||||
// End XML-RPC interface
|
||||
|
||||
// method list: ELEM_(class_name, "method_name")
|
||||
|
@ -2586,7 +2780,18 @@ public:
|
|||
ELEM_(Spot_get_auto, "spot.get_auto") \
|
||||
ELEM_(Spot_set_auto, "spot.set_auto") \
|
||||
ELEM_(Spot_toggle_auto, "spot.toggle_auto") \
|
||||
ELEM_(Spot_pskrep_get_count, "spot.pskrep.get_count")
|
||||
ELEM_(Spot_pskrep_get_count, "spot.pskrep.get_count") \
|
||||
\
|
||||
ELEM_(Wefax_state_string, "wefax.state_string") \
|
||||
ELEM_(Wefax_skip_apt, "wefax.skip_apt") \
|
||||
ELEM_(Wefax_skip_phasing, "wefax.skip_phasing") \
|
||||
ELEM_(Wefax_set_tx_abort_flag, "wefax.set_tx_abort_flag") \
|
||||
ELEM_(Wefax_end_reception, "wefax.end_reception") \
|
||||
ELEM_(Wefax_start_manual_reception, "wefax.start_manual_reception") \
|
||||
ELEM_(Wefax_set_adif_log, "wefax.set_adif_log") \
|
||||
ELEM_(Wefax_set_max_lines, "wefax.set_max_lines") \
|
||||
ELEM_(Wefax_get_received_file, "wefax.get_received_file") \
|
||||
ELEM_(Wefax_send_file, "wefax.send_file") \
|
||||
|
||||
|
||||
struct rm_pred
|
||||
|
|
|
@ -91,14 +91,20 @@ static Fl_Choice *wefax_choice_tx_lpm = (Fl_Choice *)0;
|
|||
static Fl_Round_Button *wefax_round_tx_adif_log = (Fl_Round_Button *)0;
|
||||
static Fl_Button *wefax_btn_tx_send_color = (Fl_Button *)0;
|
||||
static Fl_Button *wefax_btn_tx_send_grey = (Fl_Button *)0;
|
||||
static Fl_Output *wefax_out_tx_row_num = (Fl_Output *)0;
|
||||
static Fl_Button *wefax_btn_tx_send_abort = (Fl_Button *)0;
|
||||
static Fl_Button *wefax_btn_tx_load = (Fl_Button *)0;
|
||||
static Fl_Button *wefax_btn_tx_clear = (Fl_Button *)0;
|
||||
static Fl_Button *wefax_btn_tx_close = (Fl_Button *)0;
|
||||
|
||||
static Fl_Shared_Image *wefax_shared_tx_img = (Fl_Shared_Image *)0;
|
||||
static unsigned char *wefax_xmtimg = (unsigned char *)0;
|
||||
static unsigned char *wefax_xmtpicbuff = (unsigned char *)0;
|
||||
|
||||
/// This indicates whether an image to send is loaded in the GUI.
|
||||
/// It allows to acquire twice when re-loading an image without sending.
|
||||
static bool wefax_image_loaded_in_gui = false ;
|
||||
|
||||
/// Used for shifting the received image left and right.
|
||||
static volatile int center_val_prev = 0 ;
|
||||
|
||||
|
@ -144,6 +150,43 @@ static const int mini_max_fax_lines = 1000 ;
|
|||
/// However, when the printing resumes, the position is not altered.
|
||||
static volatile bool reception_paused = false ;
|
||||
|
||||
/// Sets the label of the received or sent image.
|
||||
static void set_win_label( Fl_Double_Window * wefax_pic, const std::string & lab)
|
||||
{
|
||||
char* label = strdup(lab.c_str());
|
||||
wefax_pic->copy_label(label);
|
||||
free(label);
|
||||
wefax_pic->redraw();
|
||||
}
|
||||
|
||||
/// Called when clearing the image to send.
|
||||
static void clear_image(void)
|
||||
{
|
||||
if (wefax_xmtimg)
|
||||
{
|
||||
delete [] wefax_xmtimg;
|
||||
wefax_xmtimg = NULL ;
|
||||
}
|
||||
if (wefax_shared_tx_img) {
|
||||
wefax_shared_tx_img->release();
|
||||
wefax_shared_tx_img = 0;
|
||||
}
|
||||
set_win_label(wefax_pic_tx_win,"");
|
||||
}
|
||||
|
||||
/// Clears the loaded image. It allows XML-RPC clients to send an image.
|
||||
static void wefax_cb_pic_tx_clear( Fl_Widget *, void *)
|
||||
{
|
||||
FL_LOCK_D();
|
||||
wefax_image_loaded_in_gui = false ;
|
||||
clear_image();
|
||||
wefax_pic_tx_picture->clear();
|
||||
wefax_pic::restart_tx_viewer();
|
||||
/// Now the lock can be acquired by XML-RPC.
|
||||
wefax_serviceme->transmit_lock_release( "Cleared" );
|
||||
FL_UNLOCK_D();
|
||||
}
|
||||
|
||||
static void wefax_cb_pic_tx_close( Fl_Widget *, void *)
|
||||
{
|
||||
FL_LOCK_D();
|
||||
|
@ -386,8 +429,7 @@ void wefax_pic::update_rx_pic_bw(unsigned char data, int pix_pos )
|
|||
/// Prints the row number sometimes only, to save CPU.
|
||||
if( ( pix_pos % 1000 ) == 0 ) {
|
||||
char row_num_buffer[20];
|
||||
snprintf( row_num_buffer, sizeof(row_num_buffer),
|
||||
"%d", row_number );
|
||||
snprintf( row_num_buffer, sizeof(row_num_buffer), "%d", row_number );
|
||||
wefax_out_rx_row_num->value( row_num_buffer );
|
||||
}
|
||||
|
||||
|
@ -439,6 +481,15 @@ static void wefax_cb_pic_rx_resume( Fl_Widget *, void *)
|
|||
wefax_serviceme->update_rx_label();
|
||||
}
|
||||
|
||||
static void LocalSleep( int seconds )
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
MilliSleep(seconds);
|
||||
#else
|
||||
usleep(100000*seconds);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Displays the latest image file saved.
|
||||
static void add_to_files_list( const std::string & the_fil_nam )
|
||||
{
|
||||
|
@ -459,22 +510,21 @@ static void add_to_files_list( const std::string & the_fil_nam )
|
|||
/// This window is hidden/shown to signal that a file was added.
|
||||
static const int nb_blink = 5 ;
|
||||
for( int ix_blink = 0 ; ix_blink < nb_blink ; ++ix_blink ) {
|
||||
#ifdef __MINGW32__
|
||||
wefax_browse_rx_events->hide();
|
||||
wefax_browse_rx_events->redraw();
|
||||
MilliSleep(1);
|
||||
LocalSleep(1);
|
||||
wefax_browse_rx_events->show();
|
||||
wefax_browse_rx_events->redraw();
|
||||
MilliSleep(1);
|
||||
#else
|
||||
wefax_browse_rx_events->hide();
|
||||
wefax_browse_rx_events->redraw();
|
||||
usleep(100000);
|
||||
wefax_browse_rx_events->show();
|
||||
wefax_browse_rx_events->redraw();
|
||||
usleep(100000);
|
||||
#endif
|
||||
LocalSleep(1);
|
||||
}
|
||||
|
||||
/// If there is not directory specification, adds the default dir.
|
||||
if( the_fil_nam.empty() )
|
||||
LOG_WARN("Empty file name");
|
||||
else if( the_fil_nam[0] != '/' )
|
||||
wefax_serviceme->put_received_file( progdefaults.wefax_save_dir + '/' + the_fil_nam );
|
||||
else
|
||||
wefax_serviceme->put_received_file( the_fil_nam );
|
||||
};
|
||||
|
||||
static void wefax_cb_pic_rx_abort( Fl_Widget *, void *)
|
||||
|
@ -628,7 +678,7 @@ static void wefax_cb_rx_set_filter( Fl_Widget *, void * )
|
|||
wefax_serviceme->set_rx_filter(ix_filter);
|
||||
}
|
||||
|
||||
static void restore_max_lines(void)
|
||||
void wefax_pic::restore_max_lines(void)
|
||||
{
|
||||
char buf_max_lines[20];
|
||||
snprintf( buf_max_lines, sizeof(buf_max_lines), "%d", wefax_serviceme->get_max_lines() );
|
||||
|
@ -643,15 +693,15 @@ static void wefax_cb_pic_max_lines( Fl_Widget *, void * )
|
|||
|
||||
/// The value given by FLTK should be an integer, but better to be sure.
|
||||
if( 1 != sscanf( ptr_val_gui, "%d", &max_val_gui ) ) {
|
||||
LOG_ERROR( "Cannot parse: %s", ptr_val_gui ) ;
|
||||
restore_max_lines();
|
||||
LOG_ERROR( _("Cannot parse: %s"), ptr_val_gui ) ;
|
||||
wefax_pic::restore_max_lines();
|
||||
return ;
|
||||
}
|
||||
|
||||
/// Faxes should not be too small otherwise we will spend all our time
|
||||
/// saving automatic image files.
|
||||
if( max_val_gui < mini_max_fax_lines ) {
|
||||
restore_max_lines();
|
||||
wefax_pic::restore_max_lines();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
@ -952,7 +1002,7 @@ void wefax_pic::create_rx_viewer(void)
|
|||
/// This buffer will never change so it does not matter if it is static.
|
||||
static char tooltip_max_lines[256];
|
||||
snprintf(tooltip_max_lines, sizeof(tooltip_max_lines),
|
||||
"Maximum number of lines per image. Must be bigger than %d",
|
||||
"Maximum number of lines per image. Minimum value is %d",
|
||||
mini_max_fax_lines );
|
||||
wefax_int_rx_max->tooltip(tooltip_max_lines);
|
||||
|
||||
|
@ -1068,11 +1118,7 @@ void wefax_pic::set_rx_label(const std::string & win_label)
|
|||
}
|
||||
|
||||
/// This copy seems strange, but otherwise the label is not updated.
|
||||
char* label = strdup(tmp_label.c_str());
|
||||
wefax_pic_rx_win->copy_label(label);
|
||||
free(label);
|
||||
|
||||
wefax_pic_rx_win->redraw_label();
|
||||
set_win_label(wefax_pic_rx_win, tmp_label);
|
||||
FL_UNLOCK_D();
|
||||
}
|
||||
|
||||
|
@ -1090,33 +1136,31 @@ void wefax_pic::save_image(const std::string & fil_name, const std::string & ext
|
|||
wefax_serviceme->qso_rec_save();
|
||||
}
|
||||
|
||||
static void wefax_load_image(const char *fil_name)
|
||||
/// Protected by an exclusive mutex.
|
||||
static std::string wefax_load_image_after_acquire(const char * fil_name)
|
||||
{
|
||||
if (wefax_serviceme != active_modem) return;
|
||||
if (wefax_serviceme != active_modem) return "Not in WEFAX mode";
|
||||
|
||||
wefax_serviceme->qso_rec_init();
|
||||
qso_notes( "TX:", fil_name );
|
||||
|
||||
if (wefax_shared_tx_img) {
|
||||
wefax_shared_tx_img->release();
|
||||
wefax_shared_tx_img = 0;
|
||||
}
|
||||
clear_image();
|
||||
wefax_shared_tx_img = Fl_Shared_Image::get(fil_name);
|
||||
if (!wefax_shared_tx_img) {
|
||||
LOG_ERROR("Could not Fl_Shared_Image::get %s", fil_name);
|
||||
return;
|
||||
std::string err_msg("Cannot call Fl_Shared_Image::get on file:" + std::string(fil_name) );
|
||||
LOG_ERROR("%s",err_msg.c_str());
|
||||
return err_msg;
|
||||
}
|
||||
if (wefax_shared_tx_img->count() > 1) { // we only handle rgb images
|
||||
LOG_ERROR("Handle only RGB images: %s", fil_name );
|
||||
wefax_shared_tx_img->release();
|
||||
wefax_shared_tx_img = 0;
|
||||
return;
|
||||
std::string err_msg("Handle only RGB images: " + std::string(fil_name) );
|
||||
LOG_ERROR("%s",err_msg.c_str());
|
||||
clear_image();
|
||||
return err_msg;
|
||||
}
|
||||
unsigned char * img_data = (unsigned char *)wefax_shared_tx_img->data()[0];
|
||||
int img_wid = wefax_shared_tx_img->w();
|
||||
int img_hei = wefax_shared_tx_img->h();
|
||||
int img_depth = wefax_shared_tx_img->d();
|
||||
if (wefax_xmtimg) delete [] wefax_xmtimg;
|
||||
wefax_xmtimg = new unsigned char [img_wid * img_hei * bytes_per_pix];
|
||||
if (img_depth == bytes_per_pix)
|
||||
memcpy(wefax_xmtimg, img_data, img_wid*img_hei*bytes_per_pix);
|
||||
|
@ -1135,22 +1179,23 @@ static void wefax_load_image(const char *fil_name)
|
|||
wefax_xmtimg[j] = wefax_xmtimg[j+1] = wefax_xmtimg[j+2] = img_data[i];
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR( "Inconsistent img_depth=%d\n", img_depth );
|
||||
exit(EXIT_FAILURE);
|
||||
std::stringstream err_strm ;
|
||||
err_strm << "Inconsistent img_depth=" << img_depth << " for " << fil_name ;
|
||||
std::string err_msg = err_strm.str();
|
||||
LOG_ERROR("%s",err_msg.c_str());
|
||||
return err_msg ;
|
||||
};
|
||||
|
||||
wefax_pic::tx_viewer_resize(img_wid, img_hei);
|
||||
|
||||
char* label = strdup(fil_name);
|
||||
wefax_pic_tx_win->copy_label(basename(label));
|
||||
free(label);
|
||||
set_win_label(wefax_pic_tx_win, fil_name);
|
||||
|
||||
wefax_pic_tx_box->label(0);
|
||||
|
||||
// load the picture widget with the rgb image
|
||||
FL_LOCK_D();
|
||||
wefax_pic_tx_picture->show();
|
||||
wefax_pic_tx_picture->clear();
|
||||
wefax_pic_tx_win->redraw();
|
||||
wefax_pic_tx_picture->video(wefax_xmtimg, img_wid * img_hei * bytes_per_pix);
|
||||
|
||||
int tim_color = wefax_serviceme->tx_time( img_wid * img_hei * bytes_per_pix );
|
||||
|
@ -1167,7 +1212,22 @@ static void wefax_load_image(const char *fil_name)
|
|||
wefax_btn_tx_send_grey->tooltip(wefax_txgry_tooltip);
|
||||
wefax_btn_tx_send_grey->activate();
|
||||
|
||||
wefax_btn_tx_clear->activate();
|
||||
|
||||
FL_UNLOCK_D();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
static void wefax_load_image(const char * fil_name)
|
||||
{
|
||||
if (wefax_serviceme != active_modem) return;
|
||||
if( false == wefax_image_loaded_in_gui )
|
||||
{
|
||||
/// So we do not re-acquire the exclusive access to wefax transmission.
|
||||
wefax_serviceme->transmit_lock_acquire(fil_name);
|
||||
wefax_image_loaded_in_gui = true ;
|
||||
}
|
||||
wefax_load_image_after_acquire(fil_name);
|
||||
}
|
||||
|
||||
void wefax_pic::set_tx_pic(unsigned char data, int col, int row, int tx_img_col, bool is_color )
|
||||
|
@ -1190,6 +1250,15 @@ void wefax_pic::set_tx_pic(unsigned char data, int col, int row, int tx_img_col,
|
|||
wefax_pic_tx_picture->pixel( data, tripleOffset + 1 );
|
||||
wefax_pic_tx_picture->pixel( data, tripleOffset + 2 );
|
||||
}
|
||||
|
||||
static int previous_row = -1 ;
|
||||
if( row != previous_row )
|
||||
{
|
||||
previous_row = row ;
|
||||
char row_num_buffer[20];
|
||||
snprintf( row_num_buffer, sizeof(row_num_buffer), "%d", row );
|
||||
wefax_out_tx_row_num->value( row_num_buffer );
|
||||
}
|
||||
}
|
||||
|
||||
static void wefax_cb_pic_tx_load(Fl_Widget *, void *)
|
||||
|
@ -1218,13 +1287,18 @@ static void wefax_pic_tx_send_common(
|
|||
FL_LOCK_D();
|
||||
|
||||
wefax_choice_tx_lpm->hide();
|
||||
wefax_round_tx_adif_log->hide();
|
||||
wefax_btn_tx_send_color->hide();
|
||||
wefax_btn_tx_send_grey->hide();
|
||||
wefax_btn_tx_load->hide();
|
||||
wefax_btn_tx_clear->hide();
|
||||
wefax_btn_tx_close->hide();
|
||||
wefax_out_tx_row_num->show();
|
||||
wefax_btn_tx_send_abort->show();
|
||||
wefax_pic_tx_picture->clear();
|
||||
|
||||
wefax_out_tx_row_num->value( "Init" );
|
||||
|
||||
wefax_serviceme->set_tx_parameters(
|
||||
get_choice_lpm_value( wefax_choice_tx_lpm ),
|
||||
wefax_xmtpicbuff,
|
||||
|
@ -1306,12 +1380,27 @@ static void wefax_cb_pic_tx_adif_log( Fl_Widget *, void *)
|
|||
|
||||
void wefax_pic::restart_tx_viewer(void)
|
||||
{
|
||||
wefax_out_tx_row_num->hide();
|
||||
wefax_btn_tx_send_abort->hide();
|
||||
wefax_choice_tx_lpm->show();
|
||||
wefax_btn_tx_send_color->show();
|
||||
wefax_btn_tx_send_grey->show();
|
||||
wefax_round_tx_adif_log->show();
|
||||
wefax_btn_tx_load->show();
|
||||
wefax_btn_tx_close->show();
|
||||
if( wefax_image_loaded_in_gui )
|
||||
{
|
||||
// If the image was loaded from the GUI.
|
||||
wefax_choice_tx_lpm->show();
|
||||
wefax_btn_tx_send_color->show();
|
||||
wefax_btn_tx_send_grey->show();
|
||||
wefax_btn_tx_clear->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
/// If the image was loaded and sent from XML-RPC, or no image present.
|
||||
wefax_choice_tx_lpm->deactivate();
|
||||
wefax_btn_tx_send_color->deactivate();
|
||||
wefax_btn_tx_send_grey->deactivate();
|
||||
wefax_btn_tx_clear->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void wefax_pic::create_tx_viewer(void)
|
||||
|
@ -1351,7 +1440,7 @@ void wefax_pic::create_tx_viewer(void)
|
|||
static const int hei_tx_btn = 24 ;
|
||||
|
||||
int width_btn = 0;
|
||||
int width_offset = 35;
|
||||
int width_offset = 30;
|
||||
|
||||
width_btn = 70 ;
|
||||
wefax_choice_tx_lpm = make_lpm_choice( width_offset, y_btn, width_btn, hei_tx_btn );
|
||||
|
@ -1366,33 +1455,46 @@ void wefax_pic::create_tx_viewer(void)
|
|||
wefax_round_tx_adif_log->align(FL_ALIGN_LEFT);
|
||||
|
||||
width_offset += width_btn ;
|
||||
width_btn = 60 ;
|
||||
wefax_btn_tx_send_color = new Fl_Button(width_offset, y_btn, width_btn, hei_tx_btn, "Xmt Color");
|
||||
width_btn = 50 ;
|
||||
wefax_btn_tx_send_color = new Fl_Button(width_offset, y_btn, width_btn, hei_tx_btn, "Tx Color");
|
||||
wefax_btn_tx_send_color->callback(wefax_cb_pic_tx_send_color, 0);
|
||||
|
||||
width_offset += width_btn ;
|
||||
width_btn = 60 ;
|
||||
wefax_btn_tx_send_grey = new Fl_Button(width_offset, y_btn, width_btn, hei_tx_btn, "Xmt Grey");
|
||||
width_btn = 50 ;
|
||||
wefax_btn_tx_send_grey = new Fl_Button(width_offset, y_btn, width_btn, hei_tx_btn, "Tx B/W");
|
||||
wefax_btn_tx_send_grey->callback( wefax_cb_pic_tx_send_grey, 0);
|
||||
|
||||
width_offset += width_btn ;
|
||||
width_btn = 40 ;
|
||||
width_btn = 35 ;
|
||||
wefax_btn_tx_load = new Fl_Button(width_offset, y_btn, width_btn, hei_tx_btn, _("Load"));
|
||||
wefax_btn_tx_load->callback(wefax_cb_pic_tx_load, 0);
|
||||
wefax_btn_tx_load->tooltip("Load image to send");
|
||||
|
||||
width_offset += width_btn ;
|
||||
width_btn = 40 ;
|
||||
width_btn = 35 ;
|
||||
wefax_btn_tx_clear = new Fl_Button(width_offset, y_btn, width_btn, hei_tx_btn, _("Clear"));
|
||||
wefax_btn_tx_clear->callback(wefax_cb_pic_tx_clear, 0);
|
||||
|
||||
width_offset += width_btn ;
|
||||
width_btn = 35 ;
|
||||
wefax_btn_tx_close = new Fl_Button(width_offset, y_btn, width_btn, hei_tx_btn, _("Close"));
|
||||
wefax_btn_tx_close->callback(wefax_cb_pic_tx_close, 0);
|
||||
|
||||
wefax_btn_tx_send_abort = new Fl_Button(84, y_btn, 122, hei_tx_btn, "Abort Xmt");
|
||||
static const char * title_row_num = "" ;
|
||||
width_offset += fl_width( title_row_num );
|
||||
wefax_out_tx_row_num = new Fl_Output(20, y_btn, 100, hei_tx_btn, _(title_row_num));
|
||||
wefax_out_tx_row_num->align(FL_ALIGN_LEFT);
|
||||
wefax_out_tx_row_num->tooltip("Fax line number being sent.");
|
||||
|
||||
wefax_btn_tx_send_abort = new Fl_Button(180, y_btn, 122, hei_tx_btn, "Abort Xmt");
|
||||
wefax_btn_tx_send_abort->callback(wefax_cb_pic_tx_send_abort, 0);
|
||||
wefax_btn_tx_send_abort->tooltip("Abort transmission");
|
||||
|
||||
wefax_out_tx_row_num->hide();
|
||||
wefax_btn_tx_send_abort->hide();
|
||||
wefax_btn_tx_send_color->deactivate();
|
||||
wefax_btn_tx_send_grey->deactivate();
|
||||
wefax_btn_tx_clear->deactivate();
|
||||
|
||||
wefax_pic_tx_win->end();
|
||||
FL_UNLOCK_D();
|
||||
|
@ -1511,4 +1613,21 @@ void wefax_pic::cb_mnu_pic_viewer(Fl_Menu_ *, void *) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Called from XML-RPC thread.
|
||||
void wefax_pic::send_image( const std::string & fil_nam )
|
||||
{
|
||||
LOG_INFO("%s", fil_nam.c_str() );
|
||||
/// Here, transmit_lock_acquire is called by the XML-RPC client.
|
||||
std::string err_msg = wefax_load_image_after_acquire( fil_nam.c_str() );
|
||||
if( ! err_msg.empty() )
|
||||
{
|
||||
if (wefax_serviceme == active_modem)
|
||||
{
|
||||
/// Allows another XML-RPC client or the GUI to send an image.
|
||||
wefax_serviceme->transmit_lock_release( err_msg );
|
||||
}
|
||||
return ;
|
||||
}
|
||||
wefax_cb_pic_tx_send_grey( NULL, NULL );
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <valarray>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
@ -277,7 +279,7 @@ static const char * state_to_str(fax_state a_state)
|
|||
case TXIMAGE : return "Sending image" ;
|
||||
case IDLE : return "Idle" ;
|
||||
}
|
||||
return "UNKOWN" ;
|
||||
return "UNKNOWN" ;
|
||||
};
|
||||
|
||||
/// TODO: This should be hidden to this class.
|
||||
|
@ -351,12 +353,6 @@ class fax_implementation {
|
|||
double m_i_fir_old;
|
||||
double m_q_fir_old;
|
||||
|
||||
/// Returns a string telling the RX state. Mostly for debugging.
|
||||
const char * state_rx_str(void) const
|
||||
{
|
||||
return state_to_str(m_rx_state);
|
||||
};
|
||||
|
||||
void decode(const int* buf, int nb_samples);
|
||||
|
||||
/// Used for transmission.
|
||||
|
@ -378,6 +374,7 @@ class fax_implementation {
|
|||
m_img_sample = 0;
|
||||
m_pix_samples_nb = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
fax_implementation(int fax_mode, wefax * ptr_wefax );
|
||||
void init_rx(int the_smpl_rate);
|
||||
|
@ -395,7 +392,7 @@ public:
|
|||
int img_w,
|
||||
int img_h,
|
||||
int xmt_bytes );
|
||||
void trx_do_next(void);
|
||||
bool trx_do_next(void);
|
||||
void tx_apt_stop(void);
|
||||
|
||||
double carrier(void) const
|
||||
|
@ -446,6 +443,21 @@ public:
|
|||
/// This generates a filename based on the frequency, current time, internal state etc...
|
||||
std::string generate_filename( const char *extra_msg ) const ;
|
||||
|
||||
std::string state_rx_str(void) const
|
||||
{
|
||||
return state_to_str(m_rx_state);
|
||||
}
|
||||
|
||||
/// Returns a string telling the state. Informational purpose.
|
||||
std::string state_string(void) const
|
||||
{
|
||||
std::stringstream result ;
|
||||
result << "tx:" << state_to_str(m_tx_state)
|
||||
<< " "
|
||||
<< "rx:" << state_to_str(m_rx_state);
|
||||
return result.str();
|
||||
};
|
||||
|
||||
private:
|
||||
/// Centered around the frequency.
|
||||
double power_usb_noise(void) const
|
||||
|
@ -685,9 +697,107 @@ private:
|
|||
void decode_apt(int x, const fax_signal & the_signal );
|
||||
void decode_phasing(int x, const fax_signal & the_signal );
|
||||
bool decode_image(int x);
|
||||
|
||||
private:
|
||||
/// Each received file has its name pushed in this queue.
|
||||
syncobj m_sync_rx ;
|
||||
std::queue< std::string > m_received_files ;
|
||||
public:
|
||||
/// Called by the engine each time a file is saved.
|
||||
void put_received_file( const std::string &filnam )
|
||||
{
|
||||
guard_lock g( m_sync_rx.mtxp() );
|
||||
LOG_INFO("%s", filnam.c_str() );
|
||||
m_received_files.push( filnam );
|
||||
m_sync_rx.signal();
|
||||
}
|
||||
|
||||
/// Returns a received file name, by chronological order.
|
||||
std::string get_received_file( double max_seconds )
|
||||
{
|
||||
guard_lock g( m_sync_rx.mtxp() );
|
||||
|
||||
LOG_INFO("delay=%f", max_seconds );
|
||||
if( m_received_files.empty() )
|
||||
{
|
||||
if( ! m_sync_rx.wait(max_seconds) ) return std::string();
|
||||
}
|
||||
std::string filnam = m_received_files.front();
|
||||
m_received_files.pop();
|
||||
return filnam ;
|
||||
}
|
||||
private:
|
||||
/// No unicity if the same filename is sent by several clients at the same time.
|
||||
/// This does not really matter because the error codes should be the same.
|
||||
syncobj m_sync_tx_fil ;
|
||||
std::string m_tx_fil ; // Filename being transmitted.
|
||||
|
||||
syncobj m_sync_tx_msg ;
|
||||
typedef std::map< std::string, std::string > sent_files_type ;
|
||||
sent_files_type m_sent_files ;
|
||||
public:
|
||||
/// If the delay is exceeded, returns with an error message.
|
||||
std::string send_file( const std::string & filnam, double max_seconds )
|
||||
{
|
||||
LOG_INFO("%s", filnam.c_str() );
|
||||
bool is_acquired = transmit_lock_acquire(filnam, max_seconds);
|
||||
if( ! is_acquired ) return "Timeout sending " + filnam ;
|
||||
|
||||
REQ( wefax_pic::send_image, filnam );
|
||||
|
||||
guard_lock g( m_sync_tx_fil.mtxp() );
|
||||
|
||||
sent_files_type::iterator itFi ;
|
||||
while(true)
|
||||
{
|
||||
itFi = m_sent_files.find( filnam );
|
||||
if( itFi != m_sent_files.end() )
|
||||
{
|
||||
break ;
|
||||
}
|
||||
if( ! m_sync_tx_msg.wait( max_seconds ) )
|
||||
{
|
||||
return "Timeout";
|
||||
}
|
||||
}
|
||||
std::string err_msg = itFi->second ;
|
||||
m_sent_files.erase( itFi );
|
||||
return err_msg ;
|
||||
}
|
||||
|
||||
/// Called when loading a file from the GUI, or indirectly from XML-RPC.
|
||||
bool transmit_lock_acquire(const std::string & filnam, double delay = wefax::max_delay )
|
||||
{
|
||||
LOG_INFO("%s", filnam.c_str() );
|
||||
guard_lock g( m_sync_tx_fil.mtxp() );
|
||||
if ( ! m_tx_fil.empty() )
|
||||
{
|
||||
if( ! m_sync_tx_fil.wait( delay ) ) return false ;
|
||||
}
|
||||
m_tx_fil = filnam ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
/// Allows to send another file. Called by XML-RPC and the GUI.
|
||||
void transmit_lock_release( const std::string & err_msg )
|
||||
{
|
||||
guard_lock g( m_sync_tx_msg.mtxp() );
|
||||
LOG_INFO("%s %s", m_tx_fil.c_str(), err_msg.c_str() );
|
||||
if( m_tx_fil.empty() )
|
||||
{
|
||||
LOG_WARN("%s File name should not be empty", err_msg.c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sent_files[ m_tx_fil ] = err_msg ;
|
||||
m_tx_fil.clear();
|
||||
}
|
||||
m_sync_tx_msg.signal();
|
||||
}
|
||||
|
||||
}; // class fax_implementation
|
||||
|
||||
/// Narrow, middle etc... input filters. Constructed at program startup.
|
||||
/// Narrow, middle etc... input filters. Constructed at program startup. Readonly.
|
||||
fir_filter_pair_set fax_implementation::m_rx_filters ;
|
||||
|
||||
fax_implementation::fax_implementation( int fax_mode, wefax * ptr_wefax )
|
||||
|
@ -704,6 +814,8 @@ fax_implementation::fax_implementation( int fax_mode, wefax * ptr_wefax )
|
|||
m_start_duration = 5 ;
|
||||
m_stop_duration = 5 ;
|
||||
m_manual_mode = false ;
|
||||
m_rx_state = IDLE ;
|
||||
m_tx_state = IDLE ;
|
||||
|
||||
int index_of_correlation ;
|
||||
/// http://en.wikipedia.org/wiki/Radiofax
|
||||
|
@ -1124,7 +1236,7 @@ void fax_implementation::skip_apt_rx(void)
|
|||
{
|
||||
wefax_pic::skip_rx_apt();
|
||||
if(m_rx_state!=RXAPTSTART) {
|
||||
LOG_ERROR("Should be in APT state. State=%s. Manual=%d", state_rx_str(), m_manual_mode );
|
||||
LOG_ERROR("Should be in APT state. State=%s. Manual=%d", state_rx_str().c_str(), m_manual_mode );
|
||||
}
|
||||
m_lpm_img=m_lpm_sum_rx=0;
|
||||
m_rx_state=RXPHASING;
|
||||
|
@ -1143,7 +1255,7 @@ void fax_implementation::skip_phasing_to_image(bool auto_center)
|
|||
|
||||
REQ( wefax_pic::skip_rx_phasing, auto_center );
|
||||
if(m_rx_state!=RXPHASING) {
|
||||
LOG_ERROR("Should be in phasing state. State=%s", state_rx_str() );
|
||||
LOG_ERROR("Should be in phasing state. State=%s", state_rx_str().c_str() );
|
||||
}
|
||||
m_rx_state=RXIMAGE;
|
||||
|
||||
|
@ -1167,7 +1279,7 @@ void fax_implementation::skip_phasing_to_image(bool auto_center)
|
|||
void fax_implementation::skip_phasing_rx(bool auto_center)
|
||||
{
|
||||
if(m_rx_state!=RXPHASING) {
|
||||
LOG_ERROR("Should be in phasing state. State=%s", state_rx_str() );
|
||||
LOG_ERROR("Should be in phasing state. State=%s", state_rx_str().c_str() );
|
||||
}
|
||||
skip_phasing_to_image(auto_center);
|
||||
|
||||
|
@ -1307,10 +1419,9 @@ void fax_implementation::modulate(const double* buffer, int number)
|
|||
m_ptr_wefax->ModulateXmtr( stack_xmt_buf, number );
|
||||
}
|
||||
|
||||
/// Returns the number of pixels written from the image.
|
||||
void fax_implementation::trx_do_next(void)
|
||||
/// Returns true if succesful
|
||||
bool fax_implementation::trx_do_next(void)
|
||||
{
|
||||
|
||||
LOG_DEBUG("m_xmt_bytes=%d m_lpm_img=%f", m_xmt_bytes, m_lpm_img );
|
||||
|
||||
/// The number of samples sent for one line. The LPM is given by the GUI.
|
||||
|
@ -1321,8 +1432,8 @@ void fax_implementation::trx_do_next(void)
|
|||
double buf[block_len];
|
||||
|
||||
bool end_of_loop = false ;
|
||||
bool tx_completed = true ;
|
||||
int curr_sample_idx = 0 , nb_samples_to_send = 0 ;
|
||||
const char * curr_status_msg = "APT start" ;
|
||||
|
||||
for(int num_bytes_to_write=0; ; ++num_bytes_to_write ) {
|
||||
bool disp_msg = ( ( num_bytes_to_write % block_len ) == 0 ) && ( num_bytes_to_write > 0 );
|
||||
|
@ -1330,9 +1441,11 @@ void fax_implementation::trx_do_next(void)
|
|||
if( disp_msg ) {
|
||||
modulate( buf, num_bytes_to_write);
|
||||
|
||||
const char * curr_status_msg = state_to_str( m_tx_state );
|
||||
/// TODO: Should be multiplied by 3 when sending in BW ?
|
||||
if( m_ptr_wefax->is_tx_finished(curr_sample_idx, nb_samples_to_send, curr_status_msg ) ) {
|
||||
end_of_loop = true ;
|
||||
tx_completed = false;
|
||||
continue ;
|
||||
};
|
||||
num_bytes_to_write = 0 ;
|
||||
|
@ -1347,7 +1460,6 @@ void fax_implementation::trx_do_next(void)
|
|||
curr_sample_idx++;
|
||||
} else {
|
||||
m_tx_state=TXPHASING;
|
||||
curr_status_msg = "Phasing" ;
|
||||
curr_sample_idx=0;
|
||||
}
|
||||
}
|
||||
|
@ -1361,7 +1473,6 @@ void fax_implementation::trx_do_next(void)
|
|||
curr_sample_idx++;
|
||||
} else {
|
||||
m_tx_state=ENDPHASING;
|
||||
curr_status_msg = "End phasing" ;
|
||||
curr_sample_idx=0;
|
||||
}
|
||||
}
|
||||
|
@ -1372,7 +1483,6 @@ void fax_implementation::trx_do_next(void)
|
|||
curr_sample_idx++;
|
||||
} else {
|
||||
m_tx_state=TXIMAGE;
|
||||
curr_status_msg = "Sending image" ;
|
||||
curr_sample_idx=0;
|
||||
}
|
||||
}
|
||||
|
@ -1447,7 +1557,6 @@ void fax_implementation::trx_do_next(void)
|
|||
}
|
||||
} else {
|
||||
m_tx_state=TXAPTSTOP;
|
||||
curr_status_msg = "APT stop" ;
|
||||
curr_sample_idx=0;
|
||||
}
|
||||
}
|
||||
|
@ -1458,12 +1567,12 @@ void fax_implementation::trx_do_next(void)
|
|||
curr_sample_idx++;
|
||||
} else {
|
||||
m_tx_state=IDLE;
|
||||
curr_status_msg = "Finished" ;
|
||||
end_of_loop = true ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
} // loop
|
||||
return tx_completed ;
|
||||
}
|
||||
|
||||
void fax_implementation::tx_params_set(
|
||||
|
@ -1724,14 +1833,20 @@ void wefax::set_tx_parameters(
|
|||
/// Callback continuously called by fldigi modem class.
|
||||
int wefax::tx_process()
|
||||
{
|
||||
m_impl->trx_do_next();
|
||||
|
||||
bool tx_was_completed = m_impl->trx_do_next();
|
||||
std::string status ;
|
||||
if( false == tx_was_completed ) {
|
||||
status = "Transmission cancelled";
|
||||
LOG_INFO("Sending cancelled" );
|
||||
m_qso_rec.putField(NOTES, status.c_str() );
|
||||
}
|
||||
qso_rec_save();
|
||||
|
||||
REQ_FLUSH(GET_THREAD_ID());
|
||||
|
||||
FL_LOCK_E();
|
||||
wefax_pic::restart_tx_viewer();
|
||||
transmit_lock_release(status);
|
||||
m_abortxmt = false;
|
||||
FL_UNLOCK_E();
|
||||
m_impl->tx_apt_stop();
|
||||
|
@ -1779,10 +1894,10 @@ void wefax::set_lpm( int the_lpm )
|
|||
return m_impl->lpm_set( the_lpm );
|
||||
}
|
||||
|
||||
/// Transmission time in seconds.
|
||||
/// Transmission time in seconds. Factor 3 if b/w image.
|
||||
int wefax::tx_time( int nb_bytes ) const
|
||||
{
|
||||
return (double)nb_bytes / modem::samplerate ;
|
||||
return (double)nb_bytes / ( modem::samplerate * 3.0 );
|
||||
}
|
||||
|
||||
/// This prints a message about the progress of image sending,
|
||||
|
@ -1825,6 +1940,7 @@ std::string wefax::suggested_filename(void) const
|
|||
return m_impl->generate_filename( "gui" );
|
||||
};
|
||||
|
||||
/// This creates a QSO record to be written to an adif file.
|
||||
void wefax::qso_rec_init(void)
|
||||
{
|
||||
if( m_adif_log == false ) {
|
||||
|
@ -1884,6 +2000,7 @@ void wefax::qso_rec_init(void)
|
|||
// m_qso_rec.putField(TX_PWR, inpTX_pwr_log->value());
|
||||
}
|
||||
|
||||
/// Called once a QSO rec has been filled with information. Saved to adif file.
|
||||
void wefax::qso_rec_save(void)
|
||||
{
|
||||
if( m_adif_log == false ) {
|
||||
|
@ -1914,3 +2031,39 @@ void wefax::set_freq(double)
|
|||
modem::set_freq(m_impl->carrier());
|
||||
}
|
||||
|
||||
// String telling the tx and rx internal state.
|
||||
std::string wefax::state_string(void) const
|
||||
{
|
||||
return m_impl->state_string();
|
||||
}
|
||||
|
||||
/// Called when a file is saved, so XML-RPC calls can get the filename.
|
||||
void wefax::put_received_file( const std::string &filnam )
|
||||
{
|
||||
m_impl->put_received_file( filnam );
|
||||
}
|
||||
|
||||
/// Returns a received file name, by chronological order.
|
||||
std::string wefax::get_received_file( double max_seconds )
|
||||
{
|
||||
return m_impl->get_received_file( max_seconds );
|
||||
}
|
||||
|
||||
/// This is not thread-safe, at all.
|
||||
std::string wefax::send_file( const std::string & filnam, double max_seconds )
|
||||
{
|
||||
return m_impl->send_file( filnam, max_seconds );
|
||||
}
|
||||
|
||||
/// Transmitting files is done in exclusive mode.
|
||||
bool wefax::transmit_lock_acquire(const std::string & filnam, double max_seconds )
|
||||
{
|
||||
return m_impl->transmit_lock_acquire( filnam, max_seconds );
|
||||
}
|
||||
|
||||
/// Called after a file is sent.
|
||||
void wefax::transmit_lock_release( const std::string & err_msg )
|
||||
{
|
||||
m_impl->transmit_lock_release( err_msg );
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue