kopia lustrzana https://github.com/jamescoxon/dl-fldigi
Upstream version 2.11M
rodzic
ded087d8f6
commit
d5b8fecd6e
|
@ -4,6 +4,10 @@ Change Log:
|
|||
2) Added mousewheel over Macro buttons to move between macro button sets.
|
||||
3) Fixed bug in Olivia signal level display.
|
||||
4) Ported to Windows (win32)
|
||||
5) Added floating digiscope and / or fixed scope abutting waterfall
|
||||
specified with command line switch --twoscopes
|
||||
Default is floating digiscope without the fixed scope
|
||||
6) Added save as png to mfsk-pic reception
|
||||
|
||||
2.10.3)
|
||||
1) Corrected memory leak bug.
|
||||
|
|
|
@ -9,7 +9,7 @@ dnl major and minor must be integers; patch may
|
|||
dnl contain other characters or be empty
|
||||
m4_define(FLDIGI_MAJOR, [2])
|
||||
m4_define(FLDIGI_MINOR, [11])
|
||||
m4_define(FLDIGI_PATCH, [L])
|
||||
m4_define(FLDIGI_PATCH, [M])
|
||||
|
||||
AC_INIT([fldigi], FLDIGI_MAJOR.FLDIGI_MINOR[FLDIGI_PATCH], [w1hkj AT w1hkj DOT com])
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ void cw::rx_init()
|
|||
smpl_ctr = 0;
|
||||
cw_rr_current = 0;
|
||||
agc_peak = 0;
|
||||
digiscope->mode(Digiscope::SCOPE);
|
||||
set_scope_mode(Digiscope::SCOPE);
|
||||
put_MODEstatus(mode);
|
||||
usedefaultWPM = false;
|
||||
}
|
||||
|
|
|
@ -104,7 +104,8 @@ Fl_Double_Window *scopeview = (Fl_Double_Window *)0;
|
|||
|
||||
MixerBase* mixer = 0;
|
||||
|
||||
bool useCheckButtons = false;
|
||||
bool useCheckButtons = false;
|
||||
bool twoscopes = false;
|
||||
|
||||
Fl_Button *btnTune = (Fl_Button *)0;
|
||||
Fl_Tile_check *TiledGroup = 0;
|
||||
|
@ -152,6 +153,8 @@ string strMacroName[NUMMACKEYS];
|
|||
|
||||
waterfall *wf = (waterfall *)0;
|
||||
Digiscope *digiscope = (Digiscope *)0;
|
||||
Digiscope *wfscope = (Digiscope *)0;
|
||||
|
||||
Fl_Slider *sldrSquelch = (Fl_Slider *)0;
|
||||
Progress *pgrsSquelch = (Progress *)0;
|
||||
|
||||
|
@ -1231,6 +1234,9 @@ int below(Fl_Widget* w)
|
|||
|
||||
void create_fl_digi_main() {
|
||||
int pad = wSpace, Y = 0;
|
||||
|
||||
if (twoscopes) WNOM -= 2*DEFAULT_SW;
|
||||
|
||||
fl_digi_main = new Fl_Double_Window(WNOM, HNOM, "fldigi");
|
||||
mnu = new Fl_Menu_Bar(0, 0, WNOM - 142, Hmenu);
|
||||
// FL_NORMAL_SIZE may have changed; update the menu items
|
||||
|
@ -1394,54 +1400,64 @@ void create_fl_digi_main() {
|
|||
|
||||
Y += Hmacros;
|
||||
|
||||
Fl_Pack *wfpack = new Fl_Pack(0, Y, WNOM, Hwfall);
|
||||
wfpack->type(1);
|
||||
pgrsSquelch = new Progress(
|
||||
0, Y+2,
|
||||
DEFAULT_SW, Hwfall-4, "");
|
||||
pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN);
|
||||
pgrsSquelch->type(Progress::VERTICAL);
|
||||
sldrSquelch = new Fl_Slider(
|
||||
FL_VERT_NICE_SLIDER,
|
||||
DEFAULT_SW, Y+2,
|
||||
DEFAULT_SW, Hwfall-4, "");
|
||||
if (twoscopes) {
|
||||
Fl_Pack *wfpack = new Fl_Pack(0, Y, WNOM, Hwfall);
|
||||
wfpack->type(1);
|
||||
wf = new waterfall(0, Y, Wwfall - Hwfall + 24, Hwfall);
|
||||
wf->end();
|
||||
Fl_Pack *ypack = new Fl_Pack(Wwfall - Hwfall + 24, Y, Hwfall - 24, Hwfall);
|
||||
ypack->type(0);
|
||||
|
||||
wfscope = new Digiscope (Wwfall - Hwfall, Y, Hwfall - 24, Hwfall - 24);
|
||||
|
||||
pgrsSquelch = new Progress(
|
||||
Wwfall - Hwfall + 24, Y + Hwfall - 24,
|
||||
Hwfall - 24, 12, "");
|
||||
pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN);
|
||||
sldrSquelch = new Fl_Slider(
|
||||
FL_HOR_NICE_SLIDER,
|
||||
Wwfall - Hwfall + 24, Y + Hwfall - 12,
|
||||
Hwfall - 24, 12, "");
|
||||
|
||||
sldrSquelch->minimum(100);
|
||||
sldrSquelch->maximum(0);
|
||||
sldrSquelch->step(1);
|
||||
sldrSquelch->value(progStatus.sldrSquelchValue);
|
||||
sldrSquelch->callback((Fl_Callback*)cb_sldrSquelch);
|
||||
sldrSquelch->color(FL_INACTIVE_COLOR);
|
||||
|
||||
// wf = new waterfall(0, Y, Wwfall, Hwfall);
|
||||
wf = new waterfall(2*DEFAULT_SW, Y, Wwfall, Hwfall);//Wwfall, Hwfall);
|
||||
wf->end();
|
||||
sldrSquelch->minimum(0);
|
||||
sldrSquelch->maximum(100);
|
||||
sldrSquelch->step(1);
|
||||
sldrSquelch->value(progStatus.sldrSquelchValue);
|
||||
sldrSquelch->callback((Fl_Callback*)cb_sldrSquelch);
|
||||
sldrSquelch->color(FL_INACTIVE_COLOR);
|
||||
|
||||
// Fl_Pack *ypack = new Fl_Pack(WNOM-(Hwfall-24 - 2*sw), Y, Hwfall-26, Hwfall);
|
||||
// ypack->type(0);
|
||||
ypack->end();
|
||||
Fl_Group::current()->resizable(wf);
|
||||
wfpack->end();
|
||||
} else {
|
||||
Fl_Pack *wfpack = new Fl_Pack(0, Y, WNOM, Hwfall);
|
||||
wfpack->type(1);
|
||||
|
||||
// digiscope = new Digiscope (2*DEFAULT_SW + Wwfall - (Hwfall - 24), Y, Hwfall-24, Hwfall-24);
|
||||
// digiscope->hide();
|
||||
|
||||
// pgrsSquelch = new Progress(
|
||||
// WNOM-(Hwfall-24), Y + Hwfall - 24,
|
||||
// Hwfall - 24, 12, "");
|
||||
// pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN);
|
||||
// sldrSquelch = new Fl_Slider(
|
||||
// FL_HOR_NICE_SLIDER,
|
||||
// WNOM-(Hwfall-24), Y + Hwfall - 12,
|
||||
// Hwfall - 24, 12, "");
|
||||
|
||||
// sldrSquelch->minimum(0);
|
||||
// sldrSquelch->maximum(100);
|
||||
// sldrSquelch->step(1);
|
||||
// sldrSquelch->value(progStatus.sldrSquelchValue);
|
||||
// sldrSquelch->callback((Fl_Callback*)cb_sldrSquelch);
|
||||
// sldrSquelch->color(FL_INACTIVE_COLOR);
|
||||
wf = new waterfall(0, Y, Wwfall, Hwfall);
|
||||
wf->end();
|
||||
|
||||
// ypack->end();
|
||||
Fl_Group::current()->resizable(wf);
|
||||
wfpack->end();
|
||||
pgrsSquelch = new Progress(
|
||||
WNOM - 2*DEFAULT_SW, Y + 4,
|
||||
DEFAULT_SW, Hwfall - 8, "");
|
||||
pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN);
|
||||
pgrsSquelch->type(Progress::VERTICAL);
|
||||
pgrsSquelch->tooltip("Detected signal level");
|
||||
|
||||
sldrSquelch = new Fl_Slider(
|
||||
FL_VERT_NICE_SLIDER,
|
||||
WNOM - DEFAULT_SW, Y + 4,
|
||||
DEFAULT_SW, Hwfall - 8, "");
|
||||
sldrSquelch->minimum(100);
|
||||
sldrSquelch->maximum(0);
|
||||
sldrSquelch->step(1);
|
||||
sldrSquelch->value(progStatus.sldrSquelchValue);
|
||||
sldrSquelch->callback((Fl_Callback*)cb_sldrSquelch);
|
||||
sldrSquelch->color(FL_INACTIVE_COLOR);
|
||||
sldrSquelch->tooltip("Squelch level");
|
||||
|
||||
Fl_Group::current()->resizable(wf);
|
||||
wfpack->end();
|
||||
}
|
||||
Y += (Hwfall + 2);
|
||||
|
||||
Fl_Pack *hpack = new Fl_Pack(0, Y, WNOM, Hstatus);
|
||||
|
@ -1526,7 +1542,10 @@ void create_fl_digi_main() {
|
|||
fl_digi_main->xclass(PACKAGE_NAME);
|
||||
|
||||
scopeview = new Fl_Double_Window(0,0,140,140, "Scope");
|
||||
scopeview->xclass(PACKAGE_NAME);
|
||||
digiscope = new Digiscope (0, 0, 140, 140);
|
||||
scopeview->resizable(digiscope);
|
||||
scopeview->size_range(50, 50, 0, 0, 0, 0, 1);
|
||||
scopeview->end();
|
||||
scopeview->hide();
|
||||
}
|
||||
|
@ -1562,28 +1581,44 @@ void put_cwRcvWPM(double wpm)
|
|||
FL_AWAKE_D();
|
||||
}
|
||||
|
||||
void set_scope_mode(Digiscope::scope_mode md)
|
||||
{
|
||||
if (digiscope)
|
||||
digiscope->mode(md);
|
||||
if (wfscope)
|
||||
wfscope->mode(md);
|
||||
}
|
||||
|
||||
void set_scope(double *data, int len, bool autoscale)
|
||||
{
|
||||
if (digiscope)
|
||||
digiscope->data(data, len, autoscale);
|
||||
if (wfscope)
|
||||
wfscope->data(data, len, autoscale);
|
||||
}
|
||||
|
||||
void set_phase(double phase, bool highlight)
|
||||
{
|
||||
if (digiscope)
|
||||
digiscope->phase(phase, highlight);
|
||||
if (wfscope)
|
||||
wfscope->phase(phase, highlight);
|
||||
}
|
||||
|
||||
void set_rtty(double flo, double fhi, double amp)
|
||||
{
|
||||
if (digiscope)
|
||||
digiscope->rtty(flo, fhi, amp);
|
||||
if (wfscope)
|
||||
wfscope->rtty(flo, fhi, amp);
|
||||
}
|
||||
|
||||
void set_video(double *data, int len)
|
||||
{
|
||||
if (digiscope)
|
||||
digiscope->video(data, len);
|
||||
if (wfscope)
|
||||
wfscope->video(data, len);
|
||||
}
|
||||
|
||||
Fl_Menu_Item *mnuLogging = (Fl_Menu_Item *)0;
|
||||
|
@ -2028,8 +2063,10 @@ void change_modem_param(int state)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (state & FL_SHIFT)
|
||||
else if (state & FL_SHIFT) {
|
||||
val = sldrSquelch;
|
||||
d = -d;
|
||||
}
|
||||
|
||||
val->value(val->clamp(val->increment(val->value(), -d)));
|
||||
bool changed_save = progdefaults.changed;
|
||||
|
|
|
@ -93,8 +93,7 @@ void dominoex::init()
|
|||
modem::init();
|
||||
restart();
|
||||
rx_init();
|
||||
// digiscope->mode(Digiscope::SCOPE);
|
||||
digiscope->mode(Digiscope::DOMDATA);
|
||||
set_scope_mode(Digiscope::DOMDATA);
|
||||
}
|
||||
|
||||
dominoex::~dominoex()
|
||||
|
|
|
@ -73,7 +73,7 @@ void feld::init()
|
|||
{
|
||||
modem::init();
|
||||
initKeyWaveform();
|
||||
digiscope->mode(Digiscope::BLANK);
|
||||
set_scope_mode(Digiscope::BLANK);
|
||||
put_MODEstatus(mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
Digiscope(int, int, int, int);
|
||||
~Digiscope();
|
||||
int handle(int);
|
||||
void resize(int x, int y, int w, int h);
|
||||
void draw();
|
||||
void draw_scope();
|
||||
void draw_phase();
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "progress.h"
|
||||
|
||||
extern Fl_Double_Window *fl_digi_main;
|
||||
extern Fl_Double_Window *scopeview;
|
||||
|
||||
extern ReceiveWidget *ReceiveText;
|
||||
extern TransmitWidget *TransmitText;
|
||||
|
@ -89,6 +90,7 @@ extern Fl_Button *btnAltMacros;
|
|||
|
||||
|
||||
extern bool useCheckButtons;
|
||||
extern bool twoscopes;
|
||||
extern int altMacros;
|
||||
|
||||
extern waterfall *wf;
|
||||
|
@ -107,6 +109,8 @@ extern void put_freq(double frequency);
|
|||
extern void put_Bandwidth(int bandwidth);
|
||||
extern void display_metric(double metric);
|
||||
extern void put_cwRcvWPM(double wpm);
|
||||
|
||||
extern void set_scope_mode(Digiscope::scope_mode md);
|
||||
extern void set_scope(double *data, int len, bool autoscale = true);
|
||||
extern void set_phase(double phase, bool highlight);
|
||||
extern void set_rtty(double, double, double);
|
||||
|
|
|
@ -29,27 +29,25 @@
|
|||
#define IDI_ICON 101
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// You can change the x1 width of the waterfall / spectrum display by modifying this
|
||||
// constant.
|
||||
// Suggest that you make the value a multiple of 100.
|
||||
// DO NOT EXCEED 4000
|
||||
// The larger the number the greater the cpu load will be for creating the
|
||||
// waterfall display
|
||||
#define DEFAULT_SW 15
|
||||
//
|
||||
// Setting the DEFAULT_IMAGE_WIDTH to 3200 will size the x1 waterfall to be
|
||||
// 800 pixels wide. The x1 waterfall size is always DEFAULT_IMAGE_WIDTH / 4
|
||||
// and the minimum width of main display would then be
|
||||
//
|
||||
// DEFAULT_IMAGE_WIDTH / 4 + 2 * BEZEL + 2 * DEFAULT_SW
|
||||
//
|
||||
// where BEZEL is set to 2 (border around the waterfall), and
|
||||
// DEFAULT_SW is the width of the signal level and squelch controls
|
||||
|
||||
#define DEFAULT_IMAGE_WIDTH 3200
|
||||
#define DEFAULT_HWFALL 144
|
||||
#define DEFAULT_HNOM 570
|
||||
#define DEFAULT_WNOM (DEFAULT_IMAGE_WIDTH / 4 + 2 * DEFAULT_SW)
|
||||
//#define DEFAULT_WNOM (DEFAULT_IMAGE_WIDTH / 4 + DEFAULT_HWFALL - BTN_HEIGHT)
|
||||
|
||||
#define EMC_HWFALL 144
|
||||
#define EMC_HNOM 500
|
||||
#define EMC_WNOM (EMC_HWFALL - BTN_HEIGHT + 500)
|
||||
|
||||
extern int IMAGE_WIDTH;
|
||||
extern int Hwfall;
|
||||
extern int HNOM;
|
||||
extern int WNOM;
|
||||
//=============================================================================
|
||||
|
||||
// widget sizes internal to the waterfall widget
|
||||
#define BEZEL 2
|
||||
|
@ -73,6 +71,21 @@ extern int WNOM;
|
|||
#define bwXmtRcv 45
|
||||
#define wSpace 2
|
||||
|
||||
#define DEFAULT_SW 15
|
||||
#define DEFAULT_HWFALL 144
|
||||
#define DEFAULT_HNOM 570
|
||||
#define Wwfall (DEFAULT_IMAGE_WIDTH / 4 + 2 * BEZEL)
|
||||
#define DEFAULT_WNOM (Wwfall + 2* DEFAULT_SW)
|
||||
|
||||
#define EMC_HWFALL 144
|
||||
#define EMC_HNOM 500
|
||||
#define EMC_WNOM (EMC_HWFALL - BTN_HEIGHT + 500)
|
||||
|
||||
extern int IMAGE_WIDTH;
|
||||
extern int Hwfall;
|
||||
extern int HNOM;
|
||||
extern int WNOM;
|
||||
|
||||
#define Hmenu 22
|
||||
#define Hqsoframe 48
|
||||
#define Hnotes 22
|
||||
|
@ -80,11 +93,9 @@ extern int WNOM;
|
|||
#define Hmacros 22
|
||||
|
||||
#define Htext (HNOM - 4 - Hwfall - Hmenu - Hstatus - Hmacros - Hqsoframe - Hnotes)
|
||||
// Htext = HNOM - 140 - Hwfall
|
||||
#define Hrcvtxt (Htext) / 2
|
||||
#define Hxmttxt (Htext - (Hrcvtxt))
|
||||
|
||||
#define Wwfall (WNOM - Hwfall + BTN_HEIGHT + 2 * BEZEL)
|
||||
#define Wmode 80
|
||||
#define Ws2n 100
|
||||
#define Wimd 100
|
||||
|
@ -94,17 +105,4 @@ extern int WNOM;
|
|||
|
||||
#define Wstatus (WNOM - Wmode - Ws2n - Wimd - bwAfcOnOff - bwSqlOnOff - Wwarn)
|
||||
|
||||
//remove the comment delimiter to enable experimental psk250 and qpsk250 modes
|
||||
|
||||
#define USE250
|
||||
|
||||
//remove the comment delimiter to enable both old and new text widget class
|
||||
//switching from one to the other requires a restart of the program before
|
||||
//the newly selected widget becomes effective.
|
||||
//
|
||||
//default is to use the new text widget class that is a fully enabled editor
|
||||
//widget
|
||||
//#define USE_BOTH_TEXT_WIDGETS
|
||||
|
||||
|
||||
#endif // FLDIGI_CONFIG_H
|
||||
|
|
|
@ -61,7 +61,8 @@ public:
|
|||
void clear();
|
||||
void image(Fl_Image *img) {Fl_Widget::image(img);}
|
||||
void resize(int, int, int, int);
|
||||
int save_jpeg(const char *);
|
||||
int save_jpeg(const char *);
|
||||
int save_png(const char *);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,11 @@ struct status {
|
|||
bool sqlonoff;
|
||||
double RcvMixer;
|
||||
double XmtMixer;
|
||||
int scopeX;
|
||||
int scopeY;
|
||||
bool scopeVisible;
|
||||
int scopeW;
|
||||
int scopeH;
|
||||
|
||||
bool bLastStateRead;
|
||||
|
||||
|
|
10
src/main.cxx
10
src/main.cxx
|
@ -352,6 +352,10 @@ void generate_option_help(void) {
|
|||
<< " If PROFILE is ``emc'', ``emcomm'', or ``minimal'',\n"
|
||||
<< " widget sizes will be adjusted for a minimal screen footprint\n\n"
|
||||
|
||||
<< " --twoscopes\n"
|
||||
<< " digiscope adjacent to waterfall and,\n"
|
||||
<< " digiscope in separate resizeable window\n\n"
|
||||
|
||||
<< " --usechkbtns\n"
|
||||
<< " Use check buttons for AFC / SQL.\n";
|
||||
|
||||
|
@ -378,6 +382,7 @@ int parse_args(int argc, char **argv, int& idx)
|
|||
#if USE_PORTAUDIO
|
||||
OPT_FRAMES_PER_BUFFER,
|
||||
#endif
|
||||
OPT_TWO_SCOPES,
|
||||
OPT_EXIT_AFTER,
|
||||
OPT_HELP, OPT_VERSION };
|
||||
|
||||
|
@ -395,6 +400,7 @@ int parse_args(int argc, char **argv, int& idx)
|
|||
{ "window-width", 1, 0, OPT_WINDOW_WIDTH },
|
||||
{ "window-height", 1, 0, OPT_WINDOW_HEIGHT },
|
||||
{ "profile", 1, 0, OPT_PROFILE },
|
||||
{ "twoscopes", 0, 0, OPT_TWO_SCOPES },
|
||||
{ "usechkbtns", 0, 0, OPT_USE_CHECK },
|
||||
|
||||
{ "resample", 1, 0, OPT_RESAMPLE },
|
||||
|
@ -479,6 +485,10 @@ int parse_args(int argc, char **argv, int& idx)
|
|||
}
|
||||
break;
|
||||
|
||||
case OPT_TWO_SCOPES:
|
||||
twoscopes = true;
|
||||
break;
|
||||
|
||||
case OPT_USE_CHECK:
|
||||
useCheckButtons = true;
|
||||
break;
|
||||
|
|
|
@ -82,7 +82,7 @@ void mfsk::init()
|
|||
{
|
||||
modem::init();
|
||||
rx_init();
|
||||
digiscope->mode(Digiscope::SCOPE);
|
||||
set_scope_mode(Digiscope::SCOPE);
|
||||
}
|
||||
|
||||
mfsk::~mfsk()
|
||||
|
@ -253,8 +253,8 @@ void mfsk::recvpic(complex z)
|
|||
|
||||
if (color) {
|
||||
pixelnbr = rgb + row + 3*col;
|
||||
updateRxPic(byte, pixelnbr);
|
||||
// REQ(&mfsk::updateRxPic, this, byte, pixelnbr);
|
||||
//! updateRxPic(byte, pixelnbr);
|
||||
REQ(updateRxPic, byte, pixelnbr);
|
||||
if (++col == picW) {
|
||||
col = 0;
|
||||
if (++rgb == 3) {
|
||||
|
@ -264,8 +264,8 @@ void mfsk::recvpic(complex z)
|
|||
}
|
||||
} else {
|
||||
for (int i = 0; i < 3; i++)
|
||||
updateRxPic(byte, pixelnbr);
|
||||
// REQ(&mfsk::updateRxPic, this, byte, pixelnbr++);
|
||||
//! updateRxPic(byte, pixelnbr++);
|
||||
REQ(updateRxPic, byte, pixelnbr++);
|
||||
}
|
||||
picf = 0.0;
|
||||
|
||||
|
@ -563,13 +563,19 @@ int mfsk::rx_process(const double *buf, int len)
|
|||
if (rxstate == RX_STATE_PICTURE) {
|
||||
if (counter++ == picturesize) {
|
||||
counter = 0;
|
||||
if (btnpicRxAbort) {
|
||||
FL_LOCK_E();
|
||||
btnpicRxAbort->hide();
|
||||
btnpicRxSave->show();
|
||||
FL_UNLOCK_E();
|
||||
}
|
||||
rxstate = RX_STATE_DATA;
|
||||
// REQ_FLUSH();
|
||||
put_status("");
|
||||
#ifndef __CYGWIN__
|
||||
//#ifndef __CYGWIN__
|
||||
string autosave_dir = HomeDir + "mfsk_pics/";
|
||||
picRx->save_jpeg(autosave_dir.c_str());
|
||||
#endif
|
||||
picRx->save_png(autosave_dir.c_str());
|
||||
//#endif
|
||||
} else
|
||||
recvpic(z);
|
||||
continue;
|
||||
|
@ -696,8 +702,8 @@ void mfsk::sendpic(unsigned char *data, int len)
|
|||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (txstate == TX_STATE_PICTURE)
|
||||
updateTxPic(data[i], this);
|
||||
// REQ(&mfsk::updateTxPic, this, data[i]);
|
||||
//! updateTxPic(data[i], this);
|
||||
REQ(updateTxPic, data[i], this);
|
||||
if (reverse)
|
||||
f = get_txfreq_woffset() - bandwidth * (data[i] - 128) / 256.0;
|
||||
else
|
||||
|
@ -877,32 +883,31 @@ void cb_picRxSave( Fl_Widget *w, void *who)
|
|||
{
|
||||
// mfsk *me = (mfsk *)who;
|
||||
const char *fn =
|
||||
file_saveas( "Save image as:", "Independent JPEG Group\t*.{jpg,jpeg}", NULL );
|
||||
file_saveas( "Save image as:", "Portable Network Graphics\t*.png", "." );
|
||||
if (!fn) return;
|
||||
picRx->save_jpeg(fn);
|
||||
picRx->save_png(fn);
|
||||
}
|
||||
|
||||
void createRxViewer(mfsk *who)
|
||||
{
|
||||
FL_LOCK_E();
|
||||
FL_LOCK_D();
|
||||
picRxWin = new Fl_Double_Window(200, 140);
|
||||
picRxWin->xclass(PACKAGE_NAME);
|
||||
picRx = new picture(2, 2, 136, 104);
|
||||
btnpicRxSave = new Fl_Button(5, 140 - 30, 60, 24,"Save");
|
||||
btnpicRxSave->callback(cb_picRxSave, who);
|
||||
#ifdef __CYGWIN__
|
||||
btnpicRxSave->hide();
|
||||
#endif
|
||||
btnpicRxAbort = new Fl_Button(70, 140 - 30, 60, 24, "Abort");
|
||||
btnpicRxAbort->callback(cb_picRxAbort, who);
|
||||
btnpicRxClose = new Fl_Button(135, 140 - 30, 60, 24, "Hide");
|
||||
btnpicRxClose->callback(cb_picRxClose, who);
|
||||
activate_mfsk_image_item(true);
|
||||
FL_UNLOCK_E();
|
||||
FL_UNLOCK_D();
|
||||
}
|
||||
|
||||
void showRxViewer(int W, int H, mfsk *who)
|
||||
{
|
||||
FL_LOCK_E();
|
||||
if (!picRxWin) createRxViewer(who);
|
||||
int winW, winH;
|
||||
int picX, picY;
|
||||
|
@ -910,16 +915,18 @@ void showRxViewer(int W, int H, mfsk *who)
|
|||
winH = H + 34;
|
||||
picX = (winW - W) / 2;
|
||||
picY = 2;
|
||||
FL_LOCK_D();
|
||||
picRxWin->size(winW, winH);
|
||||
picRx->resize(picX, picY, W, H);
|
||||
btnpicRxSave->resize(winW/2 - 65, H + 6, 60, 24);
|
||||
btnpicRxSave->hide();
|
||||
btnpicRxAbort->resize(winW/2 - 65, H + 6, 60, 24);
|
||||
btnpicRxAbort->show();
|
||||
btnpicRxClose->resize(winW/2 + 5, H + 6, 60, 24);
|
||||
picRx->clear();
|
||||
#ifndef __CYGWIN__
|
||||
picRxWin->show();
|
||||
#endif
|
||||
FL_UNLOCK_D();
|
||||
FL_UNLOCK_E();
|
||||
}
|
||||
|
||||
void load_file(const char *n) {
|
||||
|
|
|
@ -52,7 +52,14 @@ status progStatus = {
|
|||
true, // bool sqlonoff
|
||||
1.0, // double RcvMixer;
|
||||
1.0, // double XmtMixer;
|
||||
0, // int scopeX;
|
||||
0, // int scopeY;
|
||||
false, // bool scopeVisible;
|
||||
50, // int scopeW;
|
||||
50, // int scopeH;
|
||||
|
||||
false // bool bLastStateRead;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -98,6 +105,17 @@ void status::saveLastState()
|
|||
rigX = rigcontrol->x();
|
||||
rigY = rigcontrol->y();
|
||||
}
|
||||
if (scopeview) {
|
||||
if (scopeview->visible())
|
||||
scopeVisible = true;
|
||||
else
|
||||
scopeVisible = false;
|
||||
scopeX = scopeview->x();
|
||||
scopeY = scopeview->y();
|
||||
scopeW = scopeview->w();
|
||||
scopeH = scopeview->h();
|
||||
}
|
||||
|
||||
string deffname = HomeDir;
|
||||
deffname.append("fldigi.status");
|
||||
ofstream deffile(deffname.c_str(), ios::out);
|
||||
|
@ -125,6 +143,11 @@ void status::saveLastState()
|
|||
deffile << sqlonoff << endl;
|
||||
deffile << RcvMixer << endl;
|
||||
deffile << XmtMixer << endl;
|
||||
deffile << scopeX << endl;
|
||||
deffile << scopeY << endl;
|
||||
deffile << scopeVisible << endl;
|
||||
deffile << scopeW << endl;
|
||||
deffile << scopeH << endl;
|
||||
|
||||
deffile.close();
|
||||
}
|
||||
|
@ -159,6 +182,11 @@ void status::loadLastState()
|
|||
deffile >> sqlonoff;
|
||||
deffile >> RcvMixer;
|
||||
deffile >> XmtMixer;
|
||||
deffile >> scopeX;
|
||||
deffile >> scopeY;
|
||||
deffile >> scopeVisible;
|
||||
deffile >> scopeW;
|
||||
deffile >> scopeH;
|
||||
deffile.close();
|
||||
progdefaults.wfRefLevel = reflevel;
|
||||
progdefaults.wfAmpSpan = ampspan;
|
||||
|
@ -223,6 +251,10 @@ void status::initLastState()
|
|||
if (VIEWERvisible == true)
|
||||
openViewer();
|
||||
|
||||
scopeview->resize(scopeX, scopeY, scopeW, scopeH);
|
||||
if (scopeVisible == true)
|
||||
scopeview->show();
|
||||
|
||||
if (LOGenabled) {
|
||||
Fl_Menu_Item *mnulogging = getMenuItem("Log File");
|
||||
if (!mnulogging)
|
||||
|
|
|
@ -159,7 +159,7 @@ void mt63::restart()
|
|||
int err;
|
||||
|
||||
put_MODEstatus(mode);
|
||||
digiscope->mode(Digiscope::BLANK);
|
||||
set_scope_mode(Digiscope::BLANK);
|
||||
set_freq(500.0 + bandwidth / 2.0);
|
||||
|
||||
err = Tx->Preset((int)bandwidth, Interleave == 64 ? 1 : 0);
|
||||
|
|
|
@ -336,7 +336,7 @@ void olivia::init()
|
|||
{
|
||||
modem::init();
|
||||
restart();
|
||||
digiscope->mode(Digiscope::BLANK);
|
||||
set_scope_mode(Digiscope::BLANK);
|
||||
}
|
||||
|
||||
olivia::olivia()
|
||||
|
|
|
@ -83,7 +83,7 @@ void psk::rx_init()
|
|||
bitclk = 0;
|
||||
freqerr = 0.0;
|
||||
if (mailserver && progdefaults.PSKmailSweetSpot) sigsearch = SIGSEARCH;
|
||||
digiscope->mode(Digiscope::PHASE);
|
||||
set_scope_mode(Digiscope::PHASE);
|
||||
put_MODEstatus(mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ void throb::init()
|
|||
{
|
||||
modem::init();
|
||||
rx_init();
|
||||
digiscope->mode(Digiscope::SCOPE);
|
||||
set_scope_mode(Digiscope::SCOPE);
|
||||
}
|
||||
|
||||
throb::~throb()
|
||||
|
|
|
@ -345,3 +345,14 @@ int Digiscope::handle(int event)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Digiscope::resize(int x, int y, int w, int h)
|
||||
{
|
||||
delete [] vidbuf;
|
||||
delete [] vidline;
|
||||
vidbuf = new unsigned char[ 3 * (w-4) * (h-4)];
|
||||
vidline = new unsigned char[ 3 * (w-4)];
|
||||
|
||||
Fl_Widget::resize(x, y, w, h);
|
||||
mode(_mode);
|
||||
}
|
||||
|
|
|
@ -1372,6 +1372,8 @@ int waterfall::handle(int event)
|
|||
Fl_Valuator* v[] = { sldrSquelch, wfcarrier, wfRefLevel, wfAmpSpan };
|
||||
for (size_t i = 0; i < sizeof(v)/sizeof(v[0]); i++) {
|
||||
if (Fl::event_inside(v[i])) {
|
||||
if (v[i] == sldrSquelch)
|
||||
d = -d;
|
||||
v[i]->value(v[i]->clamp(v[i]->increment(v[i]->value(), -d)));
|
||||
v[i]->do_callback();
|
||||
return 1;
|
||||
|
|
|
@ -57,6 +57,7 @@ extern "C" {
|
|||
//# include "transupp.h"
|
||||
};
|
||||
|
||||
#include <png.h>
|
||||
|
||||
#include "picture.h"
|
||||
|
||||
|
@ -237,6 +238,43 @@ int picture::handle(int event)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static FILE* open_file(const char* name, const char* suffix)
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
size_t flen = strlen(name);
|
||||
if (name[flen - 1] == '/') {
|
||||
// if the name ends in a slash we will generate
|
||||
// a timestamped name in the following format:
|
||||
const char t[] = "pic_YYYY-MM-DD_HHMMSSz";
|
||||
|
||||
size_t newlen = flen + sizeof(t);
|
||||
if (suffix)
|
||||
newlen += 5;
|
||||
char* newfn = new char[newlen];
|
||||
memcpy(newfn, name, flen);
|
||||
|
||||
time_t time_sec = time(0);
|
||||
struct tm ztime;
|
||||
(void)gmtime_r(&time_sec, &ztime);
|
||||
|
||||
size_t sz;
|
||||
if ((sz = strftime(newfn + flen, newlen - flen, "pic_%F_%H%M%Sz", &ztime)) > 0) {
|
||||
strncpy(newfn + flen + sz, suffix, newlen - flen - sz);
|
||||
newfn[newlen - 1] = '\0';
|
||||
mkdir(name, 0777);
|
||||
fp = fopen(newfn, "wb");
|
||||
}
|
||||
else
|
||||
fp = NULL;
|
||||
delete [] newfn;
|
||||
}
|
||||
else
|
||||
fp = fopen(name, "wb");
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
//
|
||||
// save_jpeg - Write a captured picture to a JPEG format file.
|
||||
//
|
||||
|
@ -248,29 +286,8 @@ int picture::save_jpeg(const char *filename)
|
|||
struct jpeg_compress_struct info; // Compressor info
|
||||
struct jpeg_error_mgr err; // Error handler info
|
||||
|
||||
size_t flen = strlen(filename);
|
||||
if (filename[flen - 1] == '/') {
|
||||
// if the filename ends in a slash we will generate
|
||||
// a timestamped filename in the following format:
|
||||
const char t[] = "pic_YYYY-MM-DD_HH:MM:SSz.jpg";
|
||||
|
||||
size_t newlen = flen + sizeof(t);
|
||||
char newfn[newlen];
|
||||
memcpy(newfn, filename, flen);
|
||||
|
||||
time_t time_sec = time(0);
|
||||
struct tm ztime;
|
||||
(void)gmtime_r(&time_sec, &ztime);
|
||||
|
||||
if (strftime(newfn + flen, newlen - flen, "pic_%F_%Tz.jpg", &ztime) > 0) {
|
||||
mkdir(filename, 0777);
|
||||
if ((fp = fopen(newfn, "wb")) == NULL)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((fp = fopen(filename, "wb")) == NULL)
|
||||
return -1;
|
||||
if ((fp = open_file(filename, ".jpg")) == NULL)
|
||||
return -1;
|
||||
|
||||
// Setup the JPEG compression stuff...
|
||||
info.err = jpeg_std_error(&err);
|
||||
|
@ -302,3 +319,61 @@ int picture::save_jpeg(const char *filename)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int picture::save_png(const char* filename)
|
||||
{
|
||||
FILE* fp;
|
||||
if ((fp = open_file(filename, ".png")) == NULL)
|
||||
return -1;
|
||||
|
||||
// set up the png structures
|
||||
png_structp png;
|
||||
png_infop info;
|
||||
if ((png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
if ((info = png_create_info_struct(png)) == NULL) {
|
||||
png_destroy_write_struct(&png, png_infopp_NULL);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
png_destroy_write_struct(&png, &info);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// use an stdio stream
|
||||
png_init_io(png, fp);
|
||||
|
||||
// set png header
|
||||
png_set_IHDR(png, info, width, height, 1 << depth,
|
||||
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
// TODO: write more useful image comments
|
||||
png_text text;
|
||||
text.key = strdup("Comment");
|
||||
text.text = strdup("MFSK-16 image decoded by " PACKAGE_STRING);
|
||||
text.compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
png_set_text(png, info, &text, 1);
|
||||
|
||||
// write header
|
||||
png_write_info(png, info);
|
||||
|
||||
// write image
|
||||
png_bytep row;
|
||||
for (int i = 0; i < height; i++) {
|
||||
row = &vidbuf[i * width * depth];
|
||||
png_write_rows(png, &row, 1);
|
||||
}
|
||||
png_write_end(png, info);
|
||||
|
||||
// clean up
|
||||
free(text.key);
|
||||
free(text.text);
|
||||
png_destroy_write_struct(&png, &info);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
// Include necessary header files...
|
||||
//
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ void anal::init()
|
|||
{
|
||||
modem::init();
|
||||
rx_init();
|
||||
digiscope->mode(Digiscope::RTTY);
|
||||
set_scope_mode(Digiscope::RTTY);
|
||||
}
|
||||
|
||||
anal::~anal()
|
||||
|
|
|
@ -52,7 +52,7 @@ void wwv::rx_init()
|
|||
ticks = 0;
|
||||
calc = false;
|
||||
zoom = false;
|
||||
digiscope->mode(Digiscope::WWV);
|
||||
set_scope_mode(Digiscope::WWV);
|
||||
put_MODEstatus(mode);
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue