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