Upstream version 2.11M

pull/2/head
Stelios Bounanos 2008-04-16 12:02:33 +01:00
rodzic ded087d8f6
commit d5b8fecd6e
24 zmienionych plików z 316 dodań i 128 usunięć

Wyświetl plik

@ -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.

Wyświetl plik

@ -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])

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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()

Wyświetl plik

@ -73,7 +73,7 @@ void feld::init()
{
modem::init();
initKeyWaveform();
digiscope->mode(Digiscope::BLANK);
set_scope_mode(Digiscope::BLANK);
put_MODEstatus(mode);
}

Wyświetl plik

@ -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();

Wyświetl plik

@ -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);

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -34,6 +34,11 @@ struct status {
bool sqlonoff;
double RcvMixer;
double XmtMixer;
int scopeX;
int scopeY;
bool scopeVisible;
int scopeW;
int scopeH;
bool bLastStateRead;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);

Wyświetl plik

@ -336,7 +336,7 @@ void olivia::init()
{
modem::init();
restart();
digiscope->mode(Digiscope::BLANK);
set_scope_mode(Digiscope::BLANK);
}
olivia::olivia()

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -63,7 +63,7 @@ void throb::init()
{
modem::init();
rx_init();
digiscope->mode(Digiscope::SCOPE);
set_scope_mode(Digiscope::SCOPE);
}
throb::~throb()

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -24,6 +24,8 @@
// Include necessary header files...
//
#include <config.h>
#include <FL/Fl.H>
#include <FL/fl_draw.H>

Wyświetl plik

@ -46,7 +46,7 @@ void anal::init()
{
modem::init();
rx_init();
digiscope->mode(Digiscope::RTTY);
set_scope_mode(Digiscope::RTTY);
}
anal::~anal()

Wyświetl plik

@ -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);
}