diff --git a/fli_control/CMakeLists.txt b/fli_control/CMakeLists.txt
index 572d304..87be83a 100644
--- a/fli_control/CMakeLists.txt
+++ b/fli_control/CMakeLists.txt
@@ -2,40 +2,49 @@ cmake_minimum_required(VERSION 2.8)
set(PROJ fli_control)
project(${PROJ})
set(MINOR_VERSION "0")
-set(MID_VERSION "2")
-set(MAJOR_VERSION "0")
+set(MID_VERSION "0")
+set(MAJOR_VERSION "1")
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
message("VER: ${VERSION}")
# default flags
-set(CFLAGS -O2 -std=gnu99)
+set(CFLAGS ${CFLAGS} -O2 -std=gnu99)
+add_definitions(-D_XOPEN_SOURCE=666 -D_DEFAULT_SOURCE -D_GNU_SOURCE)
set(CMAKE_COLOR_MAKEFILE ON)
-# here is one of two variants: all .c in directory or .c files in list
-aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
-#set(SOURCES list_of_c_files)
+set(SOURCES main.c cmdlnopts.c flifunc.c)
-# cmake -DEBUG=1 -> debugging
-if(DEFINED EBUG)
+# cmake -DDEBUG=yes -> debugging
+if(DEFINED DEBUG AND DEBUG STREQUAL "yes")
set(CFLAGS ${CFLAGS} -Wextra -Wall -Werror -W)
add_definitions(-DEBUG)
+ set(CMAKE_VERBOSE_MAKEFILE "ON")
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
find_package(CFITSIO REQUIRED)
find_package(PkgConfig REQUIRED)
-set(MODULES fli>=1.71)
+set(MODULES fli>=1.71 usefull_macros)
# additional modules on condition
-if(DEFINED USEPNG)
+if(DEFINED USEPNG AND USEPNG STREQUAL "yes")
set(MODULES ${MODULES} libpng>=1.2)
add_definitions(-DUSEPNG)
endif()
pkg_check_modules(${PROJ} REQUIRED ${MODULES})
-if(DEFINED USERAW)
+if(DEFINED USERAW AND USERAW STREQUAL "yes")
add_definitions(-DUSERAW)
endif()
+if(DEFINED IMAGEVIEW AND IMAGEVIEW STREQUAL "yes")
+ list(APPEND SOURCES events.c imageview.c)
+ find_package(OpenGL REQUIRED)
+ find_package(GLUT REQUIRED)
+ find_package(X11 REQUIRED)
+ find_package(Threads REQUIRED)
+ list(APPEND ${PROJ}_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+ add_definitions(-DIMAGEVIEW)
+endif()
# change wrong behaviour with install prefix
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND CMAKE_INSTALL_PREFIX MATCHES "/usr/local")
@@ -48,7 +57,7 @@ message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}")
set(LCPATH ${CMAKE_SOURCE_DIR}/locale/ru)
if(NOT DEFINED LOCALEDIR)
- if(DEFINED DEBUG)
+ if(DEFINED DEBUG AND DEBUG STREQUAL "yes")
set(LOCALEDIR ${CMAKE_CURRENT_SOURCE_DIR}/locale)
else()
set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale)
@@ -62,8 +71,8 @@ set(RU_FILE ${LCPATH}/ru.po)
# exe file
add_executable(${PROJ} ${SOURCES} ${PO_FILE} ${MO_FILE})
-target_link_libraries(${PROJ} ${CFITSIO_LIBRARIES} ${${PROJ}_LIBRARIES})
-include_directories(${${PROJ}_INCLUDE_DIRS})
+target_link_libraries(${PROJ} ${CFITSIO_LIBRARIES} ${X11_LIBRARIES} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${${PROJ}_LIBRARIES} -lm)
+include_directories(${${PROJ}_INCLUDE_DIRS} image_view_module)
link_directories(${${PROJ}_LIBRARY_DIRS} )
add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\"
-DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\"
@@ -71,12 +80,8 @@ add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\"
-DMAJOR_VERSION=\"${MAJOR_VESION}\")
# Installation of the program
-if(NOT DEFINED DEBUG)
- INSTALL(FILES ${MO_FILE} DESTINATION "share/locale/ru/LC_MESSAGES")
- INSTALL(TARGETS ${PROJ} DESTINATION "bin")
-else()
- install(CODE "MESSAGE(\"Don't install in DEBUG mode! First run cmake without -DEBUG defined.\")")
-endif(NOT DEFINED DEBUG)
+INSTALL(FILES ${MO_FILE} DESTINATION "share/locale/ru/LC_MESSAGES")
+INSTALL(TARGETS ${PROJ} DESTINATION "bin")
find_package(Gettext REQUIRED)
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
diff --git a/fli_control/FLI_control.cflags b/fli_control/FLI_control.cflags
new file mode 100644
index 0000000..68d5165
--- /dev/null
+++ b/fli_control/FLI_control.cflags
@@ -0,0 +1 @@
+-std=c17
\ No newline at end of file
diff --git a/fli_control/FLI_control.config b/fli_control/FLI_control.config
new file mode 100644
index 0000000..b9f9edc
--- /dev/null
+++ b/fli_control/FLI_control.config
@@ -0,0 +1,8 @@
+// Add predefined macros for your project here. For example:
+// #define THE_ANSWER 42
+#define USEPNG
+#define USERAW
+#define IMAGEVIEW
+#define _GNU_SOURCE
+#define _XOPEN_SOURCE 666
+#define _DEFAULT_SOURCE
diff --git a/fli_control/FLI_control.creator b/fli_control/FLI_control.creator
new file mode 100644
index 0000000..e94cbbd
--- /dev/null
+++ b/fli_control/FLI_control.creator
@@ -0,0 +1 @@
+[General]
diff --git a/fli_control/FLI_control.creator.user b/fli_control/FLI_control.creator.user
new file mode 100644
index 0000000..97c4d8e
--- /dev/null
+++ b/fli_control/FLI_control.creator.user
@@ -0,0 +1,167 @@
+
+
+
+
+
+ EnvironmentId
+ {cf63021e-ef53-49b0-b03b-2f2570cdf3b6}
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ KOI8-R
+ false
+ 4
+ false
+ 80
+ true
+ true
+ 1
+ false
+ false
+ 1
+ true
+ true
+ 0
+ 8
+ true
+ 2
+ true
+ true
+ true
+ true
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+ true
+ Builtin.DefaultTidyAndClazy
+ 4
+
+
+
+ true
+
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ Desktop
+ {91347f2c-5221-46a7-80b1-0a054ca02f79}
+ 0
+ 0
+ 0
+
+ /home/eddy/Docs/SAO/Cameras/FLI_camera/my/fli_control
+
+
+
+ all
+
+ false
+
+
+ false
+ true
+ GenericProjectManager.GenericMakeStep
+
+ 1
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+
+ clean
+
+ true
+
+
+ false
+ true
+ GenericProjectManager.GenericMakeStep
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ По умолчанию
+ GenericProjectManager.GenericBuildConfiguration
+
+ 1
+
+
+ 0
+ Развёртывание
+ Развёртывание
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+
+ 2
+
+
+ ProjectExplorer.CustomExecutableRunConfiguration
+
+
+ false
+
+ false
+ true
+ false
+ false
+ true
+
+
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 22
+
+
+ Version
+ 22
+
+
diff --git a/fli_control/FLI_control.cxxflags b/fli_control/FLI_control.cxxflags
new file mode 100644
index 0000000..6435dfc
--- /dev/null
+++ b/fli_control/FLI_control.cxxflags
@@ -0,0 +1 @@
+-std=c++17
\ No newline at end of file
diff --git a/fli_control/FLI_control.files b/fli_control/FLI_control.files
new file mode 100644
index 0000000..c25d148
--- /dev/null
+++ b/fli_control/FLI_control.files
@@ -0,0 +1,13 @@
+cmdlnopts.c
+cmdlnopts.h
+events.c
+events.h
+flifunc.c
+flifunc.h
+imageview.c
+imageview.h
+main.c
+parseargs.c
+parseargs.h
+usefull_macros.c
+usefull_macros.h
diff --git a/fli_control/FLI_control.includes b/fli_control/FLI_control.includes
new file mode 100644
index 0000000..9c558e3
--- /dev/null
+++ b/fli_control/FLI_control.includes
@@ -0,0 +1 @@
+.
diff --git a/fli_control/cmdlnopts.c b/fli_control/cmdlnopts.c
index 99321ca..6018922 100644
--- a/fli_control/cmdlnopts.c
+++ b/fli_control/cmdlnopts.c
@@ -19,12 +19,14 @@
* MA 02110-1301, USA.
*/
#include
+#include
#include
#include
#include
#include
#include
#include
+
#include "cmdlnopts.h"
#include "usefull_macros.h"
@@ -37,9 +39,8 @@
*/
static int help;
static glob_pars G;
+glob_pars *GP = NULL;
-int rewrite_ifexists = 0, // rewrite existing files == 0 or 1
- verbose = 0; // each -v increments this value, e.g. -vvv sets it to 3
// DEFAULTS
// default global parameters
glob_pars const Gdefault = {
@@ -63,18 +64,12 @@ glob_pars const Gdefault = {
*/
myoption cmdlnopts[] = {
{"help", NO_ARGS, &help, 1, arg_none, NULL, N_("show this help")},
- {"force", NO_ARGS, &rewrite_ifexists,1,arg_none,NULL, N_("rewrite output file if exists")},
- {"verbose", NO_ARGS, NULL, 'V', arg_none, APTR(&verbose), N_("verbose level (each -v increase it)")},
+ {"rewrite", NO_ARGS, &G.rewrite,1, arg_none, NULL, N_("rewrite output file if exists")},
+ {"verbose", NO_ARGS, NULL, 'V', arg_none, APTR(&G.verbose), N_("verbose level (each -v increase it)")},
{"dark", NO_ARGS, NULL, 'd', arg_int, APTR(&G.dark), N_("not open shutter, when exposing (\"dark frames\")")},
- {"open-shutter",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_OPEN,arg_none,NULL, N_("open shutter")},
- {"close-shutter",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_CLOSE,arg_none,NULL, N_("close shutter")},
- {"shutter-on-low",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_LOW,arg_none,NULL, N_("run exposition on LOW @ pin5 I/O port")},
- {"shutter-on-high",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH,arg_none,NULL, N_("run exposition on HIGH @ pin5 I/O port")},
- {"get-ioport",NO_ARGS, NULL, 'i', arg_int, APTR(&G.getio), N_("get value of I/O port pins")},
- {"async", NO_ARGS, &G.async,1, arg_none, NULL, N_("move stepper motor asynchronous")},
{"8bit", NO_ARGS, NULL, '8', arg_int, APTR(&G._8bit), N_("run in 8-bit mode")},
{"fast", NO_ARGS, NULL, 'F', arg_int, APTR(&G.fast), N_("fast (8MHz) readout mode")},
- //{"", NO_ARGS, NULL, '', arg_int, APTR(&G.), N_("")},
+ {"set-temp",NEED_ARG, NULL, 't', arg_double, APTR(&G.temperature),N_("set CCD temperature to given value (degr C)")},
{"author", NEED_ARG, NULL, 'A', arg_string, APTR(&G.author), N_("program author")},
{"objtype", NEED_ARG, NULL, 'Y', arg_string, APTR(&G.objtype), N_("object type (neon, object, flat etc)")},
@@ -83,7 +78,6 @@ myoption cmdlnopts[] = {
{"obsname", NEED_ARG, NULL, 'N', arg_string, APTR(&G.observers), N_("observers' names")},
{"prog-id", NEED_ARG, NULL, 'P', arg_string, APTR(&G.prog_id), N_("observing program name")},
{"addrec", MULT_PAR, NULL, 'r', arg_string, APTR(&G.addhdr), N_("add records to header from given file[s]")},
- //{"", NEED_ARG, NULL, '', arg_string, APTR(&G.), N_("")},
{"nflushes",NEED_ARG, NULL, 'f', arg_int, APTR(&G.nflushes), N_("N flushes before exposing")},
{"hbin", NEED_ARG, NULL, 'h', arg_int, APTR(&G.hbin), N_("horizontal binning to N pixels")},
@@ -95,15 +89,25 @@ myoption cmdlnopts[] = {
{"Y0", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y0), N_("frame Y0 coordinate (-1 - all with overscan)")},
{"X1", NEED_ARG, NULL, 0, arg_int, APTR(&G.X1), N_("frame X1 coordinate (-1 - all with overscan)")},
{"Y1", NEED_ARG, NULL, 0, arg_int, APTR(&G.Y1), N_("frame Y1 coordinate (-1 - all with overscan)")},
+
+ {"open-shutter",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_OPEN,arg_none,NULL, N_("open shutter")},
+ {"close-shutter",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_CLOSE,arg_none,NULL, N_("close shutter")},
+ {"shutter-on-low",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_LOW,arg_none,NULL, N_("run exposition on LOW @ pin5 I/O port")},
+ {"shutter-on-high",NO_ARGS,&G.shtr_cmd,FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH,arg_none,NULL, N_("run exposition on HIGH @ pin5 I/O port")},
+ {"get-ioport",NO_ARGS, NULL, 'i', arg_int, APTR(&G.getio), N_("get value of I/O port pins")},
+ {"async", NO_ARGS, &G.async,1, arg_none, NULL, N_("move stepper motor asynchronous")},
+
{"set-ioport",NEED_ARG, NULL, 's', arg_int, APTR(&G.setio), N_("set I/O port pins to given value (decimal number, pin1 is LSB)")},
{"conf-ioport",NEED_ARG,NULL, 'c', arg_int, APTR(&G.confio), N_("configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == output, 0 == input)")},
+
{"goto", NEED_ARG, NULL, 'g', arg_int, APTR(&G.gotopos), N_("move focuser to absolute position")},
{"addsteps",NEED_ARG, NULL, 'a', arg_int, APTR(&G.addsteps), N_("move focuser to relative position")},
-// {"wheel-get",NO_ARGS, NULL, 0, arg_none, APTR(&G.getwheel), N_("get current wheel position")},
- {"wheel-set",NEED_ARG, NULL, 'w', arg_int, APTR(&G.setwheel), N_("set wheel position")},
- //{"", NEED_ARG, NULL, '', arg_int, APTR(&G.), N_("")},
- {"set-temp",NEED_ARG, NULL, 't', arg_double, APTR(&G.temperature),N_("set CCD temperature to given value (degr C)")},
+ {"wheel-set",NEED_ARG, NULL, 'w', arg_int, APTR(&G.setwheel), N_("set wheel position")},
+
+#ifdef IMAGEVIEW
+ {"display", NO_ARGS, NULL, 'D', arg_int, APTR(&G.showimage), N_("Display image in OpenGL window")},
+#endif
//{"", NEED_ARG, NULL, '', arg_double, APTR(&G.), N_("")},
end_option
@@ -133,6 +137,21 @@ glob_pars *parse_args(int argc, char **argv){
printf("\t%4d: %s\n", i, argv[i]);
}
}
- return &G;
+ GP = &G;
+ return GP;
}
+/**
+ * @brief verbose - print additional messages depending of G.verbose
+ * @param levl - message level
+ * @param fmt - message
+ */
+void verbose(int levl, const char *fmt, ...){
+ va_list ar;
+ if(levl > G.verbose) return;
+ printf("%s: ", __progname);
+ va_start(ar, fmt);
+ vprintf(fmt, ar);
+ va_end(ar);
+ printf("\n");
+}
diff --git a/fli_control/cmdlnopts.h b/fli_control/cmdlnopts.h
index 47e2540..aa0bf8a 100644
--- a/fli_control/cmdlnopts.h
+++ b/fli_control/cmdlnopts.h
@@ -23,7 +23,7 @@
#ifndef __CMDLNOPTS_H__
#define __CMDLNOPTS_H__
-#include "parseargs.h"
+#include
/*
* here are some typedef's for global data
@@ -53,16 +53,19 @@ typedef struct{
double temperature; // temperature of CCD
int gotopos; // move stepper motor of focuser to absolute position
int addsteps; // move stepper motor of focuser to relative position
-// int getwheel; // get position of wheel
int setwheel; // set wheel position
int async; // asynchronous moving
+ int verbose; // each '-V' increases it
+ int rewrite; // rewrite file
+ int showimage; // show image preview
char **addhdr; // list of files from which to add header records
} glob_pars;
// default & global parameters
extern glob_pars const Gdefault;
-extern int rewrite_ifexists, verbose;
+extern glob_pars *GP;
glob_pars *parse_args(int argc, char **argv);
+void verbose(int levl, const char *fmt, ...);
#endif // __CMDLNOPTS_H__
diff --git a/fli_control/events.c b/fli_control/events.c
new file mode 100644
index 0000000..2d413dc
--- /dev/null
+++ b/fli_control/events.c
@@ -0,0 +1,199 @@
+/*
+ * events.c
+ *
+ * Copyright 2015 Edward V. Emelianov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include
+
+#include "events.h"
+#include "imageview.h"
+
+/**
+ * manage pressed keys & menu items
+ */
+static void processKeybrd(unsigned char key, int mod, _U_ int x, _U_ int y){
+ windowData *win = getWin();
+ if(!win) return;
+ DBG("key=%d (%c), mod=%d", key, key, mod);
+ if(mod == GLUT_ACTIVE_CTRL){ // 'a' == 1, 'b' == 2...
+ key += 'a'-1;
+ DBG("CTRL+%c", key);
+ switch(key){
+ case 'r': // roll colorfun
+ win->winevt |= WINEVT_ROLLCOLORFUN;
+ break;
+ case 's': // save image
+ win->winevt |= WINEVT_SAVEIMAGE;
+ break;
+ case 'q': // exit case 17:
+ win->killthread = 1;
+ break;
+ }
+ }else if(mod == GLUT_ACTIVE_ALT){
+ ; // ALT
+ }else switch(key){
+ case '0': // return zoom to 1 & image to 0
+ win->zoom = 1;
+ win->x = 0; win->y = 0;
+ break;
+ case 27: // esc - kill
+ win->killthread = 1;
+ break;
+ case 'c': // capture in pause mode
+ DBG("winevt = %d", win->winevt);
+ if(win->winevt & WINEVT_PAUSE)
+ win->winevt |= WINEVT_GETIMAGE;
+ break;
+ case 'l': // flip left-right
+ win->flip ^= WIN_FLIP_LR;
+ break;
+ case 'p': // pause capturing
+ win->winevt ^= WINEVT_PAUSE;
+ break;
+ case 'u': // flip up-down
+ win->flip ^= WIN_FLIP_UD;
+ break;
+ case 'Z': // zoom+
+ win->zoom *= 1.1f;
+ calc_win_props(NULL, NULL);
+ break;
+ case 'z': // zoom-
+ win->zoom /= 1.1f;
+ calc_win_props(NULL, NULL);
+ break;
+ }
+}
+
+/*
+ * Process keyboard
+ */
+void keyPressed(unsigned char key, int x, int y){
+ int mod = glutGetModifiers();
+ //mod: GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, GLUT_ACTIVE_ALT; result is their sum
+ DBG("Key pressed. mod=%d, keycode=%d (%c), point=(%d,%d)\n", mod, key, key, x,y);
+ processKeybrd(key, mod, x, y);
+}
+/*
+void keySpPressed(_U_ int key, _U_ int x, _U_ int y){
+// int mod = glutGetModifiers();
+ DBG("Sp. key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", glutGetModifiers(), key, x,y);
+}*/
+
+static int oldx, oldy; // coordinates when mouse was pressed
+static int movingwin = 0; // ==1 when user moves image by middle button
+
+void mousePressed(int key, int state, int x, int y){
+// key: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON
+// state: GLUT_UP, GLUT_DOWN
+ int mod = glutGetModifiers();
+ windowData *win = getWin();
+ if(!win) return;
+ if(state == GLUT_DOWN){
+ oldx = x; oldy = y;
+ float X,Y, Zoom = win->zoom;
+ conv_mouse_to_image_coords(x,y,&X,&Y,win);
+ DBG("press in (%d, %d) == (%f, %f) on image; mod == %d", x,y,X,Y, mod);
+ if(key == GLUT_LEFT_BUTTON){
+ DBG("win->x=%g, win->y=%g", win->x, win->y);
+ win->x += Zoom * (win->w/2.f - (float)x);
+ win->y -= Zoom * (win->h/2.f - (float)y);
+ }else if(key == GLUT_MIDDLE_BUTTON) movingwin = 1;
+ else if(key == 3){ // wheel UP
+ if(mod == 0) win->y += 10.f*win->zoom; // nothing pressed - scroll up
+ else if(mod == GLUT_ACTIVE_SHIFT) win->x -= 10.f*Zoom; // shift pressed - scroll left
+ else if(mod == GLUT_ACTIVE_CTRL) win->zoom *= 1.1f; // ctrl+wheel up == zoom+
+ }else if(key == 4){ // wheel DOWN
+ if(mod == 0) win->y -= 10.f*win->zoom; // nothing pressed - scroll down
+ else if(mod == GLUT_ACTIVE_SHIFT) win->x += 10.f*Zoom; // shift pressed - scroll right
+ else if(mod == GLUT_ACTIVE_CTRL) win->zoom /= 1.1f; // ctrl+wheel down == zoom-
+ }
+ calc_win_props(NULL, NULL);
+ }else{
+ movingwin = 0;
+ }
+}
+
+void mouseMove(int x, int y){
+ windowData *win = getWin();
+ if(!win) return;
+ if(movingwin){
+ float X, Y, nx, ny, w2, h2;
+ float a = win->Daspect;
+ X = (x - oldx) * a; Y = (y - oldy) * a;
+ nx = win->x + X;
+ ny = win->y - Y;
+ w2 = win->image->w / 2.f * win->zoom;
+ h2 = win->image->h / 2.f * win->zoom;
+ if(nx < w2 && nx > -w2)
+ win->x = nx;
+ if(ny < h2 && ny > -h2)
+ win->y = ny;
+ oldx = x;
+ oldy = y;
+ calc_win_props(NULL, NULL);
+ }
+}
+
+void menuEvents(int opt){
+ DBG("opt: %d, key: %d (%c), mod: %d", opt, opt&0xff, opt&0xff, opt>>8);
+ // just work as shortcut pressed
+ processKeybrd((unsigned char)(opt&0xff), opt>>8, 0, 0);
+} // GLUT_ACTIVE_CTRL
+
+typedef struct{
+ char *name; // menu entry name
+ int symbol; // shortcut symbol + rolled modifier
+} menuentry;
+
+#define CTRL_K(key) ((key-'a'+1) | (GLUT_ACTIVE_CTRL<<8))
+#define SHIFT_K(key) (key | (GLUT_ACTIVE_SHIFT<<8))
+#define ALT_K(key) (key | (GLUT_ACTIVE_ALT<<8))
+static const menuentry entries[] = {
+ {"Capture in pause mode (c)", 'c'},
+ {"Flip image LR (l)", 'l'},
+ {"Flip image UD (u)", 'u'},
+ {"Make a pause/continue (p)", 'p'},
+ {"Restore zoom (0)", '0'},
+ {"Roll colorfun (ctrl+r)", CTRL_K('r')},
+ {"Save image (ctrl+s)", CTRL_K('s')},
+ {"Close this window (ESC)", 27},
+ {"Quit (ctrl+q)", CTRL_K('q')},
+ {NULL, 0}
+};
+#undef CTRL_K
+#undef SHIFT_K
+#undef ALT_K
+
+void createMenu(){
+ FNAME();
+ windowData *win = getWin();
+ if(!win) return;
+ DBG("menu for win ID %d", win->ID);
+ glutSetWindow(win->ID);
+ if(win->menu) glutDestroyMenu(win->menu);
+ win->menu = glutCreateMenu(menuEvents);
+ const menuentry *ptr = entries;
+ while(ptr->name){
+ glutAddMenuEntry(ptr->name, ptr->symbol);
+ ++ptr;
+ }
+ DBG("created menu %d\n", win->menu);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
diff --git a/fli_control/events.h b/fli_control/events.h
new file mode 100644
index 0000000..c5a4c72
--- /dev/null
+++ b/fli_control/events.h
@@ -0,0 +1,42 @@
+/*
+ * events.h
+ *
+ * Copyright 2015 Edward V. Emelianov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#pragma once
+#ifndef __EVENTS_H__
+#define __EVENTS_H__
+
+#include
+#include
+#include
+#include
+#include
+
+extern float Z; // Z (zoom)
+
+void keyPressed(unsigned char key, int x, int y);
+//void keySpPressed(int key, int x, int y);
+void mousePressed(int key, int state, int x, int y);
+void mouseMove(int x, int y);
+void createMenu();
+void menuEvents(int opt);
+//void mouseWheel(int button, int dir, int x, int y);
+
+#endif // __EVENTS_H__
diff --git a/fli_control/flifunc.c b/fli_control/flifunc.c
new file mode 100644
index 0000000..576afd0
--- /dev/null
+++ b/fli_control/flifunc.c
@@ -0,0 +1,817 @@
+/*
+ * This file is part of the FLI_control project.
+ * Copyright 2020 Edward V. Emelianov .
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#ifdef USEPNG
+#include
+#include
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "cmdlnopts.h"
+#include "flifunc.h"
+#ifdef IMAGEVIEW
+#include "imageview.h"
+#endif
+
+#define TRYFUNC(f, ...) \
+do{ if((fli_err = f(__VA_ARGS__))) \
+ WARNX(#f "() failed"); \
+}while(0)
+
+#define TRYFITS(f, ...) \
+do{ int status = 0; \
+ f(__VA_ARGS__, &status); \
+ if (status){ \
+ fits_report_error(stderr, status); \
+ return -1;} \
+}while(0)
+#define WRITEKEY(...) \
+do{ int status = 0; \
+ fits_write_key(__VA_ARGS__, &status); \
+ if(status) fits_report_error(stderr, status);\
+}while(0)
+
+static long fli_err;
+static char *camera = NULL;
+static double t_ext, t_int; // external & CCD temperatures @exp. end
+static time_t expStartsAt; // exposition start time (time_t)
+static long filterpos = -1; // filter position
+static long focuserpos = -1; // focuser position
+
+static int writefits(char *filename, int width, int height, void *data);
+#ifdef USEPNG
+static int writepng(char *filename, int width, int height, void *data);
+#endif
+#ifdef USERAW
+static int writeraw(char *filename, int width, int height, void *data);
+#endif // USERAW
+
+typedef struct{
+ flidomain_t domain;
+ char *dname;
+ char *name;
+}cam_t;
+
+#define TMBUFSIZ 40
+static char tm_buf[TMBUFSIZ]; // buffer for string with time value
+
+static uint16_t max = 0, min = 65535; // max/min values for given image
+static double avr, std; // stat values
+static char viewfield[80];
+static double pixX, pixY; // pixel size in um
+
+static void print_stat(u_int16_t *img, long size);
+
+static size_t curtime(char *s_time){ // current date/time
+ time_t tm = time(NULL);
+ return strftime(s_time, TMBUFSIZ, "%d/%m/%Y,%H:%M:%S", localtime(&tm));
+}
+
+static fliframe_t frametype = FLI_FRAME_TYPE_NORMAL;
+
+static int check_filename(char *buff, char *outfile, char *ext){
+ struct stat filestat;
+ int num;
+ for(num = 1; num < 10000; num++){
+ if(snprintf(buff, BUFF_SIZ, "%s_%04d.%s", outfile, num, ext) < 1)
+ return 0;
+ if(stat(buff, &filestat)) // no such file or can't stat()
+ return 1;
+ }
+ return 0;
+}
+
+// return 0 if OK
+int fli_init(){
+ char libver[LIBVERSIZ]; // FLI library version
+ // #ifdef EBUG
+ TRYFUNC(FLISetDebugLevel, NULL /* "NO HOST" */, FLIDEBUG_NONE);
+ /* #else
+ TRYFUNC(FLISetDebugLevel, NULL, FLIDEBUG_...);
+ #endif */
+ if(fli_err){
+ WARNX("Can't clear debug level");
+ return 1;
+ }
+ TRYFUNC(FLIGetLibVersion, libver, LIBVERSIZ);
+ // '%s'
+ if(!fli_err) verbose(1, _("Library version '%s'"), libver);
+ return 0;
+}
+
+static int findcams(flidomain_t domain, cam_t **cam){
+ char **tmplist;
+ int numcams = 0;
+ TRYFUNC(FLIList, domain, &tmplist);
+ if (tmplist && tmplist[0]){
+ int i, cams = 0;
+ for (i = 0; tmplist[i]; i++) cams++;
+ if ((*cam = realloc(*cam, (numcams + cams) * sizeof(cam_t))) == NULL)
+ ERR("realloc() failed");
+ for (i = 0; tmplist[i]; i++){
+ int j;
+ cam_t *tmpcam = *cam + i;
+ for (j = 0; tmplist[i][j] != '\0'; j++)
+ if (tmplist[i][j] == ';'){
+ tmplist[i][j] = '\0';
+ break;
+ }
+ tmpcam->domain = domain;
+ tmpcam->name = strdup(tmplist[i]);
+ switch (domain & 0xff){
+ case FLIDOMAIN_PARALLEL_PORT:
+ tmpcam->dname = "parallel port";
+ break;
+ case FLIDOMAIN_USB:
+ tmpcam->dname = "USB";
+ ;
+ break;
+ case FLIDOMAIN_SERIAL:
+ tmpcam->dname = "serial";
+ break;
+ case FLIDOMAIN_INET:
+ tmpcam->dname = "inet";
+ break;
+ default:
+ tmpcam->dname = "Unknown domain";
+ break;
+ }
+ DBG("found: %s @ %s", tmpcam->name, tmpcam->dname);
+ }
+ numcams += cams;
+ }
+ else DBG("No devices");
+ TRYFUNC(FLIFreeList, tmplist);
+ return numcams;
+}
+
+static void print_stat(u_int16_t *img, long size){
+ long i, Noverld = 0L;
+ double pv, sum=0., sum2=0., sz = (double)size;
+ u_int16_t *ptr = img, val;
+ max = 0; min = 65535;
+ for(i = 0; i < size; i++, ptr++){
+ val = *ptr;
+ pv = (double) val;
+ sum += pv;
+ sum2 += (pv * pv);
+ if(max < val) max = val;
+ if(min > val) min = val;
+ if(val >= 65530) Noverld++;
+ }
+ // :\n
+ printf(_("Image stat:\n"));
+ avr = sum/sz;
+ printf("avr = %.1f, std = %.1f, Noverload = %ld\n", avr,
+ std = sqrt(fabs(sum2/sz - avr*avr)), Noverld);
+ printf("max = %u, min = %u, size = %ld\n", max, min, size);
+}
+
+/*
+ * Find focusers and work with each of them
+ */
+void focusers(){
+ flidev_t dev;
+ int nfocs = 0;
+ long ltmp;
+ char buff[BUFF_SIZ];
+ cam_t *cam = NULL;
+ int num = findcams(FLIDOMAIN_USB | FLIDEVICE_FOCUSER, &cam);
+ for(int i = 0; i < num; i++){
+ TRYFUNC(FLIOpen, &dev, cam[i].name, cam[i].domain);
+ if(fli_err) continue;
+ TRYFUNC(FLIGetModel, dev, buff, BUFF_SIZ);
+ if(!fli_err){
+ if(!strcasestr(buff, "focuser")){ // not focuser
+ TRYFUNC(FLIClose, dev);
+ continue;
+ }
+ // :\t\t%s
+ verbose(1, _("Model:\t\t%s"), buff);
+ }
+ ++nfocs;
+ verbose(1, _("Focuser '%s', domain %s"), cam[i].name, cam[i].dname);
+ TRYFUNC(FLIGetHWRevision, dev, <mp);
+ // . : %ld
+ if(!fli_err) verbose(1, _("HW revision: %ld"), ltmp);
+ TRYFUNC(FLIGetFWRevision, dev, <mp);
+ // . : %ld
+ if(!fli_err) verbose(1, _("SW revision: %ld"), ltmp);
+ TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_INTERNAL, &t_ext);
+ if(!fli_err) green("FOCTEMP=%.1f\n", t_ext);
+ long curpos = -1, maxpos = -1;
+ TRYFUNC(FLIGetStepperPosition, dev, <mp);
+ if(!fli_err){
+ curpos = ltmp;
+ }
+ TRYFUNC(FLIGetFocuserExtent, dev, <mp);
+ if(!fli_err){
+ green("FOCMAXPOS=%ld\n", ltmp);
+ maxpos = ltmp;
+ }
+ do{
+ if(GP->gotopos != INT_MAX && GP->addsteps != INT_MAX){
+ //
+ WARNX(_("You can't use both relative and absolute position"));
+ break;
+ }
+ if(curpos < 0 || maxpos < 0){
+ //
+ WARNX(_("Error in position detection"));
+ break;
+ }
+ long pos = -1, steps = 0;
+ if(GP->gotopos != INT_MAX){ // absolute pointing
+ pos = GP->gotopos;
+ steps = pos - curpos;
+ }else if(GP->addsteps != INT_MAX){ // relative pointing
+ steps = GP->addsteps;
+ pos = curpos + steps;
+ }else break;
+ if(!steps){
+ verbose(1, _("Already at position"));
+ break;
+ }
+ if(pos > maxpos || pos < 0){
+ // 0...%ld
+ WARNX(_("Position should be in 0...%ld"), maxpos);
+ break;
+ }
+ if(pos == 0){
+ //
+ verbose(1, _("Moving to home position"));
+ if(GP->async) TRYFUNC(FLIHomeDevice, dev);
+ else TRYFUNC(FLIHomeFocuser, dev);
+ }else{
+ // %ld
+ verbose(1, _("Moving for %ld steps"), steps);
+ if(GP->async) TRYFUNC(FLIStepMotorAsync, dev, steps);
+ else TRYFUNC(FLIStepMotor, dev, steps);
+ }
+ }while(0);
+ TRYFUNC(FLIGetStepperPosition, dev, &focuserpos);
+ if(!fli_err){
+ green("FOCPOS=%ld\n", focuserpos);
+ curpos = focuserpos;
+ }else DBG("Error getting fpos: %ld", fli_err);
+ TRYFUNC(FLIClose, dev);
+ }
+ if(!nfocs) WARNX(_("No focusers found"));
+ for(int i = 0; i < num; i++) FREE(cam[i].name);
+ FREE(cam);
+}
+
+/*
+ * Find wheels and work with each of them
+ */
+void wheels(){
+ cam_t *cam = NULL;
+ flidev_t dev;
+ long ltmp;
+ char buff[BUFF_SIZ];
+ int nwheels = 0;
+ int num = findcams(FLIDOMAIN_USB | FLIDEVICE_FILTERWHEEL, &cam);
+ for(int i = 0; i < num; i++){
+ TRYFUNC(FLIOpen, &dev, cam[i].name, cam[i].domain);
+ if(fli_err) continue;
+ TRYFUNC(FLIGetFilterCount, dev, <mp);
+ if(fli_err || ltmp < 2){// not a wheel
+ TRYFUNC(FLIClose, dev);
+ continue;
+ }
+ verbose(1, _("Wheel '%s', domain %s"), cam[i].name, cam[i].dname);
+ green("WHEELTOTALPOS=%ld\n", ltmp);
+ int wheelmaxpos = (int)ltmp - 1;
+ TRYFUNC(FLIGetModel, dev, buff, BUFF_SIZ);
+ // :\t\t%s
+ if(!fli_err) verbose(1, _("Model:\t\t%s"), buff);
+ TRYFUNC(FLIGetHWRevision, dev, <mp);
+ // . : %ld
+ if(!fli_err) verbose(1, _("HW revision: %ld"), ltmp);
+ TRYFUNC(FLIGetFWRevision, dev, <mp);
+ // . : %ld
+ if(!fli_err) verbose(1, _("SW revision: %ld"), ltmp);
+ else goto closewheeldev;
+ if(GP->setwheel > -1 && GP->setwheel >= ltmp){
+ GP->setwheel = -1;
+ WARNX(_("Wheel position should be from 0 to %ld"), ltmp - 1);
+ }
+ ++nwheels;
+ if(GP->setwheel > -1){
+ ltmp = GP->setwheel;
+ if(ltmp > wheelmaxpos){
+ WARNX(_("Position is too big (max %d)"), wheelmaxpos);
+ goto closewheeldev;
+ }
+ TRYFUNC(FLISetFilterPos, dev, ltmp);
+ if(!fli_err) verbose(1, _("Arrive to position"));
+ }
+ // this function returns -1 every connection without SETpos!!!
+ TRYFUNC(FLIGetFilterPos, dev, &filterpos);
+ if(!fli_err && filterpos > -1){
+ green("WHEELPOS=%ld\n", filterpos);
+ }else{
+ filterpos = -1;
+ // so try to check current position by steps
+ TRYFUNC(FLIGetStepperPosition, dev, <mp);
+ if(ltmp < 0) ltmp = -ltmp;
+ DBG("steps: %ld", ltmp);
+ if(!fli_err){
+ int pos = (ltmp - WHEEL_POS0STPS+WHEEL_STEPPOS/2)/WHEEL_STEPPOS;
+ DBG("pos = %d", pos);
+ if(pos > -1 && pos <= wheelmaxpos){
+ filterpos = pos;
+ green("WHEELPOS=%ld\n", filterpos);
+ }
+ }
+ }
+closewheeldev:
+ TRYFUNC(FLIClose, dev);
+ }
+ if(!nwheels) WARNX(_("No wheels found"));
+ for (int i = 0; i < num; i++)
+ FREE(cam[i].name);
+ FREE(cam);
+}
+
+/**
+ * @brief grabImage - grab image into `ima`
+ * @param ima (io) - prepared IMG structure with allocated data & initialized sizes
+ * @param dev - device
+ */
+static void grabImage(IMG *ima, flidev_t dev){
+ FNAME();
+ long ltmp;
+ TRYFUNC(FLIGetTemperature, dev, &GP->temperature); // temperature @ exp. start
+ TRYFUNC(FLIExposeFrame, dev);
+ expStartsAt = time(NULL); //
+ do{
+ TRYFUNC(FLIGetTemperature, dev, &t_int);
+ TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext);
+ if(curtime(tm_buf)){
+ // /
+ verbose(1, "%s: %s\tText=%.2f\tTint=%.2f\n", _("date/time"), tm_buf, t_ext, t_int);
+ }
+ else WARNX("curtime() error");
+ TRYFUNC(FLIGetExposureStatus, dev, <mp);
+ if(fli_err) continue;
+ if(GP->shtr_cmd > 0 && GP->shtr_cmd & FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL && ltmp == GP->exptime){
+ // " "
+ printf(_("wait for external trigger...\n"));
+ sleep(1);
+ }else{
+ // %.3f \n
+ printf(_("%.3f seconds till exposition ends\n"), ((float)ltmp) / 1000.);
+ if(ltmp > 10000) sleep(10);
+ else usleep(ltmp * 1000);
+ }
+ }while(ltmp);
+ // :
+ printf(_("Read image: "));
+ int portion = 0;
+ for(int row = 0; row < ima->h; row++){
+ TRYFUNC(FLIGrabRow, dev, &ima->data[row * ima->w], ima->w);
+ if(fli_err) break;
+ int progress = (int)(((float)row / (float)ima->h) * 100.);
+ if(progress/5 > portion){
+ if((++portion)%2) printf("..");
+ else printf("%d%%", portion*5);
+ fflush(stdout);
+ }
+ }
+ printf("100%%\n");
+ curtime(tm_buf);
+ print_stat(ima->data, ima->h*ima->w);
+}
+
+/*
+ * Find CCDs and work with each of them
+ */
+void ccds(){
+#ifdef IMAGEVIEW
+ windowData *mainwin = NULL;
+ if(GP->showimage) imageview_init();
+#endif
+ cam_t *cam = NULL;
+ flidev_t dev;
+ long ltmp;
+ char buff[BUFF_SIZ];
+ int num = findcams(FLIDOMAIN_USB | FLIDEVICE_CAMERA, &cam);
+ if(!num) WARNX(_("No CCD found"));
+ for(int i = 0; i < num; i++){
+ long x0,x1, y0,y1, img_rows, row_width;
+ // '%s' %s
+ verbose(1, _("Camera '%s', domain %s"), cam[i].name, cam[i].dname);
+ TRYFUNC(FLIOpen, &dev, cam[i].name, cam[i].domain);
+ if(fli_err) continue;
+ TRYFUNC(FLIGetModel, dev, buff, BUFF_SIZ);
+ // :\t\t%s
+ if(!fli_err) verbose(1, _("Model:\t\t%s"), buff);
+ camera = strdup(buff);
+ TRYFUNC(FLIGetHWRevision, dev, <mp);
+ // . : %ld
+ if(!fli_err) verbose(1, _("HW revision: %ld"), ltmp);
+ TRYFUNC(FLIGetFWRevision, dev, <mp);
+ // . : %ld
+ if(!fli_err) verbose(1, _("SW revision: %ld"), ltmp);
+ TRYFUNC(FLIGetPixelSize, dev, &pixX, &pixY);
+ // : %g x %g
+ if(!fli_err) verbose(1, _("Pixel size: %g x %g"), pixX, pixY);
+ TRYFUNC(FLIGetVisibleArea, dev, &x0, &y0, &x1, &y1);
+ snprintf(viewfield, 80, "(%ld, %ld)(%ld, %ld)", x0, y0, x1, y1);
+ // : %s
+ if(!fli_err) verbose(1, _("Field of view: %s"), viewfield);
+ if(GP->X1 > x1) GP->X1 = x1;
+ if(GP->Y1 > y1) GP->Y1 = y1;
+ TRYFUNC(FLIGetArrayArea, dev, &x0, &y0, &x1, &y1);
+ // : (%ld, %ld)(%ld, %ld)
+ if(!fli_err) verbose(1, _("Array field: (%ld, %ld)(%ld, %ld)"), x0, y0, x1, y1);
+ TRYFUNC(FLISetHBin, dev, GP->hbin);
+ TRYFUNC(FLISetVBin, dev, GP->vbin);
+ if(GP->X0 == -1) GP->X0 = x0; // default values
+ if(GP->Y0 == -1) GP->Y0 = y0;
+ if(GP->X1 == -1) GP->X1 = x1;
+ if(GP->Y1 == -1) GP->Y1 = y1;
+ row_width = (GP->X1 - GP->X0) / GP->hbin;
+ img_rows = (GP->Y1 - GP->Y0) / GP->vbin;
+ TRYFUNC(FLISetImageArea, dev, GP->X0, GP->Y0,
+ GP->X0 + (GP->X1 - GP->X0) / GP->hbin, GP->Y0 + (GP->Y1 - GP->Y0) / GP->vbin);
+ TRYFUNC(FLISetNFlushes, dev, GP->nflushes);
+ if(GP->temperature < 40.){
+ // " : %g \n"
+ green(_("Set CCD temperature to %g degr.C\n"), GP->temperature);
+ TRYFUNC(FLISetTemperature, dev, GP->temperature);
+ }
+ TRYFUNC(FLIGetTemperature, dev, &t_int);
+ if(!fli_err) green("CCDTEMP=%.1f\n", t_int);
+ TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext);
+ if(!fli_err) green("EXTTEMP=%.1f\n", t_ext);
+ if(GP->shtr_cmd > -1){
+ flishutter_t shtr = GP->shtr_cmd;
+ char *str = NULL;
+ switch(shtr){
+ case FLI_SHUTTER_CLOSE:
+ str = "close";
+ break;
+ case FLI_SHUTTER_OPEN:
+ str = "open";
+ break;
+ case FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_LOW:
+ str = "open @ LOW";
+ break;
+ case FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH:
+ str = "open @ HIGH";
+ break;
+ default:
+ str = "WTF?";
+ }
+ green(_("%s CCD shutter\n"), str);
+ TRYFUNC(FLIControlShutter, dev, shtr);
+ }
+ if(GP->confio > -1){
+ // " I/O %d\n"
+ green(_("Try to convfigure I/O port as %d\n"), GP->confio);
+ TRYFUNC(FLIConfigureIOPort, dev, GP->confio);
+ }
+ if(GP->getio){
+ long iop;
+ TRYFUNC(FLIReadIOPort, dev, &iop);
+ if(!fli_err) green("CCDIOPORT=0x%02lx\n", iop);
+ }
+ if(GP->setio > -1){
+ // " %d I/O\n"
+ green(_("Try to write %d to I/O port\n"), GP->setio);
+ TRYFUNC(FLIWriteIOPort, dev, GP->setio);
+ }
+
+ if(GP->exptime < DBL_EPSILON) continue;
+ TRYFUNC(FLISetExposureTime, dev, GP->exptime);
+ if(GP->dark) frametype = FLI_FRAME_TYPE_DARK;
+ TRYFUNC(FLISetFrameType, dev, frametype);
+ if(GP->_8bit){
+ TRYFUNC(FLISetBitDepth, dev, FLI_MODE_8BIT);
+ if(fli_err == 0) green(_("8 bit mode\n"));
+ }
+ TRYFUNC(FLISetCameraMode, dev, GP->fast ? 0 : 1);
+ if(GP->fast) green(_("Fast readout mode\n"));
+ if(!GP->outfile) red(_("Only show statistics\n"));
+ uint16_t *img = MALLOC(uint16_t, img_rows * row_width);
+ IMG ima = {.data = img, .w = row_width, .h = img_rows};
+ for(int j = 0; j < GP->nframes; j ++){
+ printf("\n\n");
+ // %d\n
+ printf(_("Capture frame %d\n"), j);
+ grabImage(&ima, dev);
+ saveImages(&ima, GP->outfile);
+#ifdef IMAGEVIEW
+ if(GP->showimage){ // display image
+ if(!(mainwin = getWin())){
+ DBG("Create new win");
+ mainwin = createGLwin("Sample window", row_width, img_rows, NULL);
+ if(!mainwin){
+ WARNX("Can't open OpenGL window, image preview will be inaccessible");
+ }else
+ pthread_create(&mainwin->thread, NULL, &image_thread, (void*)&ima);
+ }
+ if((mainwin = getWin())){
+ DBG("change image");
+ change_displayed_image(mainwin, &ima);
+ while((mainwin = getWin())){ // test paused state & grabbing custom frames
+ if((mainwin->winevt & WINEVT_PAUSE) == 0) break;
+ if(mainwin->winevt & WINEVT_GETIMAGE){
+ mainwin->winevt &= ~WINEVT_GETIMAGE;
+ grabImage(&ima, dev);
+ change_displayed_image(mainwin, &ima);
+ }
+ usleep(10000);
+ }
+ }
+ }
+#endif
+ if(GP->pause_len && j != (GP->nframes - 1)){
+ double delta, time1 = dtime() + GP->pause_len;
+ while((delta = time1 - dtime()) > 0.){
+ // %d \n
+ printf(_("%d seconds till pause ends\n"), (int)delta);
+ TRYFUNC(FLIGetTemperature, dev, &t_int);
+ TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext);
+ if(curtime(tm_buf)){
+ // /
+ verbose(1, "%s: %s\tText=%.2f\tTint=%.2f\n", _("date/time"), tm_buf, t_ext, t_int);
+ }
+ else verbose(1, "curtime() error");
+ if(delta > 10) sleep(10);
+ else sleep((int)delta);
+ }
+ }
+ }
+#ifdef IMAGEVIEW
+ if(GP->showimage){
+ mainwin->winevt |= WINEVT_PAUSE;
+ DBG("Waiting");
+ while((mainwin = getWin())){
+ if(mainwin->killthread) break;
+ if(mainwin->winevt & WINEVT_GETIMAGE){
+ DBG("GRAB");
+ mainwin->winevt &= ~WINEVT_GETIMAGE;
+ grabImage(&ima, dev);
+ change_displayed_image(mainwin, &ima);
+ }
+ }
+ DBG("Close window");
+ usleep(10000);
+ }
+#endif
+ FREE(camera);
+ FREE(img);
+ TRYFUNC(FLIClose, dev);
+ }
+ for(int i = 0; i < num; i++)
+ FREE(cam[i].name);
+ FREE(cam);
+}
+
+void saveImages(IMG *img, char *filename){
+ inline void WRITEIMG(int (*writefn)(char*,int,int,void*), char *ext){
+ char buff[BUFF_SIZ];
+ if(filename == NULL) return;
+ if(!check_filename(buff, filename, ext) && !GP->rewrite)
+ //
+ WARNX(_("Can't save file"));
+ else{
+ if(GP->rewrite){
+ DBG("REW");
+ char *p = "";
+ if(strcmp(ext, "fit") == 0) p = "!";
+ snprintf(buff, BUFF_SIZ, "%s%s.%s", p, filename, ext);
+ }
+ TRYFUNC(writefn, buff, img->w, img->h, (void*)img->data);
+ // '%s'
+ if (fli_err == 0) verbose(1, _("File saved as '%s'"), buff);
+ }
+ }
+ #ifdef USERAW
+ WRITEIMG(writeraw, "raw");
+ #endif
+ WRITEIMG(writefits, "fit");
+ #ifdef USEPNG
+ WRITEIMG(writepng, "png");
+ #endif
+}
+
+#ifdef USERAW
+static int writeraw(char *filename, int width, int height, void *data){
+ int fd, size, err;
+ if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) == -1){
+ WARN("open(%s) failed", filename);
+ return -errno;
+ }
+ size = width * height * sizeof(u_int16_t);
+ if ((err = write(fd, data, size)) != size){
+ WARN("write() failed");
+ err = -errno;
+ }
+ else err = 0;
+ close(fd);
+ return err;
+}
+#endif // USERAW
+
+/**
+ * @brief addrec - add FITS records from file
+ * @param f (i) - FITS filename
+ * @param filename (i) - name of file
+ */
+static void addrec(fitsfile *f, char *filename){
+ FILE *fp = fopen(filename, "r");
+ if(!fp) return;
+ char buf[2*FLEN_CARD];
+ while(fgets(buf, 2*FLEN_CARD, fp)){
+ DBG("check record _%s_", buf);
+ int keytype, status = 0;
+ char newcard[FLEN_CARD], keyname[FLEN_CARD];
+ fits_parse_template(buf, newcard, &keytype, &status);
+ if(status){
+ fits_report_error(stderr, status);
+ continue;
+ }
+ DBG("reformatted to _%s_", newcard);
+ strncpy(keyname, newcard, FLEN_CARD);
+ char *eq = strchr(keyname, '='); if(eq) *eq = 0;
+ eq = strchr(keyname, ' '); if(eq) *eq = 0;
+ DBG("keyname: %s", keyname);
+ fits_update_card(f, keyname, newcard, &status);
+ }
+}
+
+static int writefits(char *filename, int width, int height, void *data){
+ long naxes[2] = {width, height}, startTime;
+ double tmp = 0.0;
+ struct tm *tm_starttime;
+ char buf[FLEN_CARD];
+ time_t savetime = time(NULL);
+ fitsfile *fp;
+ TRYFITS(fits_create_file, &fp, filename);
+ TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes);
+ // FILE / Input file original name
+ WRITEKEY(fp, TSTRING, "FILE", filename, "Input file original name");
+ // ORIGIN / organization responsible for the data
+ WRITEKEY(fp, TSTRING, "ORIGIN", "SAO RAS", "organization responsible for the data");
+ // OBSERVAT / Observatory name
+ WRITEKEY(fp, TSTRING, "OBSERVAT", "Special Astrophysical Observatory, Russia", "Observatory name");
+ // DETECTOR / detector
+ if(camera){
+ WRITEKEY(fp, TSTRING, "DETECTOR", camera, "Detector model");
+ }
+ // INSTRUME / Instrument
+ if(GP->instrument){
+ WRITEKEY(fp, TSTRING, "INSTRUME", GP->instrument, "Instrument");
+ }else
+ WRITEKEY(fp, TSTRING, "INSTRUME", "direct imaging", "Instrument");
+ snprintf(buf, 80, "%.g x %.g", pixX, pixY);
+ // PXSIZE / pixel size
+ WRITEKEY(fp, TSTRING, "PXSIZE", buf, "Pixel size in m");
+ WRITEKEY(fp, TSTRING, "VIEWFLD", viewfield, "Camera field of view");
+ // CRVAL1, CRVAL2 / Offset in X, Y
+ if(GP->X0) WRITEKEY(fp, TINT, "X0", &GP->X0, "Subframe left border");
+ if(GP->Y0) WRITEKEY(fp, TINT, "Y0", &GP->Y0, "Subframe upper border");
+ if(GP->exptime < 2.*DBL_EPSILON) sprintf(buf, "bias");
+ else if(frametype == FLI_FRAME_TYPE_DARK) sprintf(buf, "dark");
+ else if(GP->objtype) strncpy(buf, GP->objtype, FLEN_CARD-1);
+ else sprintf(buf, "object");
+ // IMAGETYP / object, flat, dark, bias, scan, eta, neon, push
+ WRITEKEY(fp, TSTRING, "IMAGETYP", buf, "Image type");
+ // DATAMAX, DATAMIN / Max,min pixel value
+ int itmp = 0;
+ WRITEKEY(fp, TINT, "DATAMIN", &itmp, "Min pixel value");
+ //itmp = GP->fast ? 255 : 65535;
+ itmp = 65535;
+ WRITEKEY(fp, TINT, "DATAMAX", &itmp, "Max pixel value");
+ WRITEKEY(fp, TUSHORT, "STATMAX", &max, "Max data value");
+ WRITEKEY(fp, TUSHORT, "STATMIN", &min, "Min data value");
+ WRITEKEY(fp, TDOUBLE, "STATAVR", &avr, "Average data value");
+ WRITEKEY(fp, TDOUBLE, "STATSTD", &std, "Std. of data value");
+ WRITEKEY(fp, TDOUBLE, "TEMP0", &GP->temperature, "Camera temperature at exp. start (degr C)");
+ WRITEKEY(fp, TDOUBLE, "TEMP1", &t_int, "Camera temperature at exp. end (degr C)");
+ WRITEKEY(fp, TDOUBLE, "TEMPBODY", &t_ext, "Camera body temperature at exp. end (degr C)");
+ tmp = (GP->temperature + t_int) / 2. + 273.15;
+ // CAMTEMP / Camera temperature (K)
+ WRITEKEY(fp, TDOUBLE, "CAMTEMP", &tmp, "Camera temperature (K)");
+ // WHEEL & FOCUSER positions:
+ tmp = (double)focuserpos / FOCSCALE;
+ WRITEKEY(fp, TDOUBLE, "FOCUS", &tmp, "Current focuser position, mm");
+ if(filterpos > -1)
+ WRITEKEY(fp, TINT, "FILTER", &filterpos, "Current filter number");
+ // EXPTIME / actual exposition time (sec)
+ tmp = (double)GP->exptime / 1000.;
+ WRITEKEY(fp, TDOUBLE, "EXPTIME", &tmp, "Actual exposition time (sec)");
+ // DATE / Creation date (YYYY-MM-DDThh:mm:ss, UTC)
+ strftime(buf, 80, "%Y-%m-%dT%H:%M:%S", gmtime(&savetime));
+ WRITEKEY(fp, TSTRING, "DATE", buf, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)");
+ startTime = (long)expStartsAt;
+ tm_starttime = localtime(&expStartsAt);
+ strftime(buf, 80, "Exposition start time (UNIX)", tm_starttime);
+ WRITEKEY(fp, TLONG, "UNIXTIME", &startTime, buf);
+ strftime(buf, 80, "%Y/%m/%d", tm_starttime);
+ // DATE-OBS / DATE (YYYY/MM/DD) OF OBS.
+ WRITEKEY(fp, TSTRING, "DATE-OBS", buf, "DATE OF OBS. (YYYY/MM/DD, local)");
+ strftime(buf, 80, "%H:%M:%S", tm_starttime);
+ // START / Measurement start time (local) (hh:mm:ss)
+ WRITEKEY(fp, TSTRING, "START", buf, "Measurement start time (hh:mm:ss, local)");
+ // OBJECT / Object name
+ if(GP->objname){
+ WRITEKEY(fp, TSTRING, "OBJECT", GP->objname, "Object name");
+ }
+ // BINNING / Binning
+ if(GP->hbin != 1 || GP->vbin != 1){
+ snprintf(buf, 80, "%d x %d", GP->hbin, GP->vbin);
+ WRITEKEY(fp, TSTRING, "BINNING", buf, "Binning (hbin x vbin)");
+ }
+ // OBSERVER / Observers
+ if(GP->observers){
+ WRITEKEY(fp, TSTRING, "OBSERVER", GP->observers, "Observers");
+ }
+ // PROG-ID / Observation program identifier
+ if(GP->prog_id){
+ WRITEKEY(fp, TSTRING, "PROG-ID", GP->prog_id, "Observation program identifier");
+ }
+ // AUTHOR / Author of the program
+ if(GP->author){
+ WRITEKEY(fp, TSTRING, "AUTHOR", GP->author, "Author of the program");
+ }
+ if(GP->addhdr){ // add records from files
+ char **nxtfile = GP->addhdr;
+ while(*nxtfile){
+ addrec(fp, *nxtfile++);
+ }
+ }
+ TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, data);
+ TRYFITS(fits_close_file, fp);
+ return 0;
+}
+
+#ifdef USEPNG
+static int writepng(char *filename, int width, int height, void *data){
+ int err;
+ FILE *fp = NULL;
+ png_structp pngptr = NULL;
+ png_infop infoptr = NULL;
+ void *row;
+ if ((fp = fopen(filename, "wb")) == NULL){
+ err = -errno;
+ goto done;
+ }
+ if ((pngptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL)) == NULL){
+ err = -ENOMEM;
+ goto done;
+ }
+ if ((infoptr = png_create_info_struct(pngptr)) == NULL){
+ err = -ENOMEM;
+ goto done;
+ }
+ png_init_io(pngptr, fp);
+ png_set_compression_level(pngptr, Z_BEST_COMPRESSION);
+ png_set_IHDR(pngptr, infoptr, width, height, 16, PNG_COLOR_TYPE_GRAY,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+ png_write_info(pngptr, infoptr);
+ png_set_swap(pngptr);
+ for(row = data; height > 0; row += width * sizeof(u_int16_t), height--)
+ png_write_row(pngptr, row);
+ png_write_end(pngptr, infoptr);
+ err = 0;
+ done:
+ if(fp) fclose(fp);
+ if(pngptr) png_destroy_write_struct(&pngptr, &infoptr);
+ return err;
+}
+#endif /* USEPNG */
+
+
diff --git a/fli_control/flifunc.h b/fli_control/flifunc.h
new file mode 100644
index 0000000..ed81307
--- /dev/null
+++ b/fli_control/flifunc.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the FLI_control project.
+ * Copyright 2020 Edward V. Emelianov .
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#ifndef FLIFUNC_H__
+#define FLIFUNC_H__
+
+#include
+#include
+
+#define LIBVERSIZ 1024
+#define BUFF_SIZ 4096
+
+#ifndef FLIUSB_VENDORID
+#define FLIUSB_VENDORID 0xf18
+#endif
+#ifndef FLIUSB_PROLINE_ID
+#define FLIUSB_PROLINE_ID 0x0a
+#endif
+#ifndef FLIUSB_FILTER_ID
+#define FLIUSB_FILTER_ID 0x07
+#endif
+#ifndef FLIUSB_FOCUSER_ID
+#define FLIUSB_FOCUSER_ID 0x06
+#endif
+
+// wheel position in steps = WHEEL_POS0STPS + WHEEL_STEPPOS*N
+#define WHEEL_POS0STPS (239)
+#define WHEEL_STEPPOS (48)
+// 1mm == FOCSCALE steps of focuser
+#define FOCSCALE (10000.)
+
+typedef struct{
+ uint16_t *data;
+ int w;
+ int h;
+} IMG;
+
+int fli_init();
+void focusers();
+void wheels();
+void ccds();
+void saveImages(IMG *img, char *filename);
+
+#endif // FLIFUNC_H__
diff --git a/fli_control/imageview.c b/fli_control/imageview.c
new file mode 100644
index 0000000..5f577fe
--- /dev/null
+++ b/fli_control/imageview.c
@@ -0,0 +1,463 @@
+/*
+ * This file is part of the FLI_control project.
+ * Copyright 2020 Edward V. Emelianov .
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include // XInitThreads();
+#include // roundf(), log(), sqrt()
+#include
+#include
+#include
+
+#include "cmdlnopts.h"
+#include "imageview.h"
+
+static windowData *win = NULL; // main window
+static pthread_t GLUTthread = 0; // main GLUT thread
+
+static int initialized = 0; // ==1 if GLUT is initialized; ==0 after clear_GL_context
+
+static void *Redraw(_U_ void *p);
+static void createWindow();
+static void RedrawWindow();
+static void Resize(int width, int height);
+
+/**
+ * calculate window properties on creating & resizing
+ */
+void calc_win_props(GLfloat *Wortho, GLfloat *Hortho){
+ if(!win || ! win->image) return;
+ float a, A, w, h, W, H;
+ float Zoom = win->zoom;
+ w = (float)win->image->w / 2.f;
+ h = (float)win->image->h / 2.f;
+ W = (float)win->w;
+ H =(float) win->h;
+ A = W / H;
+ a = w / h;
+ if(A > a){ // now W & H are parameters for glOrtho
+ win->Daspect = (float)h / H * 2.f;
+ W = h * A; H = h;
+ }else{
+ win->Daspect = (float)w / W * 2.f;
+ H = w / A; W = w;
+ }
+ if(Wortho) *Wortho = W;
+ if(Hortho) *Hortho = H;
+ // calculate coordinates of center
+ win->x0 = W/Zoom - w + win->x / Zoom;
+ win->y0 = H/Zoom + h - win->y / Zoom;
+}
+
+/**
+ * create window & run main loop
+ */
+static void createWindow(){
+ DBG("ini=%d, win %s", initialized, win ? "yes" : "no");
+ if(!initialized) return;
+ if(!win) return;
+ int w = win->w, h = win->h;
+ DBG("create window with title %s", win->title);
+ glutInitWindowSize(w, h);
+ win->ID = glutCreateWindow(win->title);
+ DBG("created GL_ID=%d", win->ID);
+ glutReshapeFunc(Resize);
+ glutDisplayFunc(RedrawWindow);
+ glutKeyboardFunc(keyPressed);
+ //glutSpecialFunc(keySpPressed);
+ //glutMouseWheelFunc(mouseWheel);
+ glutMouseFunc(mousePressed);
+ glutMotionFunc(mouseMove);
+ //glutIdleFunc(glutPostRedisplay);
+ glutIdleFunc(RedrawWindow);
+ DBG("init textures");
+ glGenTextures(1, &(win->Tex));
+ calc_win_props(NULL, NULL);
+ win->zoom = 1. / win->Daspect;
+ glEnable(GL_TEXTURE_2D);
+ // the hext 4 lines need to unaligned storage
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glBindTexture(GL_TEXTURE_2D, win->Tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, win->image->w, win->image->h, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glDisable(GL_TEXTURE_2D);
+ createMenu();
+ DBG("Window opened");
+}
+
+int killwindow(){
+ if(!win) return 0;
+ if(!win->killthread){
+ // say threads to die
+ win->killthread = 1;
+ }
+ pthread_mutex_lock(&win->mutex);
+ //pthread_join(win->thread, NULL); // wait while thread dies
+ if(win->menu) glutDestroyMenu(win->menu);
+ glutDestroyWindow(win->ID);
+ DBG("destroy menu, wundow & texture %d", win->Tex);
+ glDeleteTextures(1, &(win->Tex));
+ glutLeaveMainLoop();
+ DBG("Cancel");
+ windowData *old = win;
+ win = NULL;
+ DBG("free(rawdata)");
+ FREE(old->image->rawdata);
+ DBG("free(image)");
+ FREE(old->image);
+ pthread_mutex_unlock(&old->mutex);
+ DBG("free(win)");
+ FREE(old);
+ DBG("return");
+ return 1;
+}
+
+void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color){
+ if(!initialized) return;
+ char *c;
+ int x1=x, W=0;
+ for(c = string; *c; c++){
+ W += glutBitmapWidth(font,*c);// + 1;
+ }
+ x1 -= W/2;
+ glColor3ubv(color);
+ glLoadIdentity();
+ glTranslatef(0.,0., -150);
+ //glTranslatef(x,y, -4000.);
+ for (c = string; *c != '\0'; c++){
+ glColor3ubv(color);
+ glRasterPos2f(x1,y);
+ glutBitmapCharacter(font, *c);
+ //glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
+ x1 = x1 + glutBitmapWidth(font,*c);// + 1;
+ }
+}
+
+static void RedrawWindow(){
+ //DBG("ini=%d, win=%s", initialized, win ? "yes" : "no");
+ if(!initialized || !win || win->killthread) return;
+ if(pthread_mutex_trylock(&win->mutex)) return;
+ GLfloat w = win->image->w, h = win->image->h;
+ glutSetWindow(win->ID);
+ glClearColor(0.0, 0.0, 0.5, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+ glTranslatef(win->x, win->y, 0.);
+ glScalef(-win->zoom, -win->zoom, 1.);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, win->Tex);
+ if(win->image->changed){
+ DBG("Image changed!");
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, win->image->w, win->image->h, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);
+ /* glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, win->image->w, win->image->h,
+ GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);*/
+ win->image->changed = 0;
+ }
+ w /= 2.f; h /= 2.f;
+ float lr = 1., ud = 1.; // flipping coefficients
+ if(win->flip & WIN_FLIP_LR) lr = -1.;
+ if(win->flip & WIN_FLIP_UD) ud = -1.;
+ glBegin(GL_QUADS);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f( -1.f*lr*w, ud*h ); // top right
+ glTexCoord2f(1.0f, 0.0f); glVertex2f( -1.f*lr*w, -1.f*ud*h ); // bottom right
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(lr*w, -1.f*ud*h ); // bottom left
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(lr*w, ud*h ); // top left
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+ glFinish();
+ glutSwapBuffers();
+ pthread_mutex_unlock(&win->mutex);
+ usleep(10000);
+}
+
+/**
+ * main freeGLUT loop
+ * waits for global signals to create windows & make other actions
+ */
+static void *Redraw(_U_ void *arg){
+ FNAME();
+ createWindow();
+ glutMainLoop();
+ return NULL;
+}
+
+static void Resize(int width, int height){
+ FNAME();
+ if(!initialized || !win || win->killthread) return;
+ glutReshapeWindow(width, height);
+ win->w = width;
+ win->h = height;
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ GLfloat W, H;
+ calc_win_props(&W, &H);
+ glOrtho(-W,W, -H,H, -1., 1.);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+/**
+ * create new window, run thread & return pointer to its structure or NULL
+ * asynchroneous call from outside
+ * wait for window creating & return its data
+ * @param title - header (copyed inside this function)
+ * @param w,h - image size
+ * @param rawdata - NULL (then the memory will be allocated here with size w x h)
+ * or allocated outside data
+ */
+windowData *createGLwin(char *title, int w, int h, rawimage *rawdata){
+ FNAME();
+ if(!initialized) imageview_init();
+ if(win) killwindow();
+ win = MALLOC(windowData, 1);
+ rawimage *raw;
+ if(rawdata){
+ raw = rawdata;
+ }else{
+ raw = MALLOC(rawimage, 1);
+ if(raw){
+ raw->rawdata = MALLOC(GLubyte, w*h*3);
+ raw->w = w;
+ raw->h = h;
+ raw->changed = 1;
+ // raw->protected is zero automatically
+ }
+ }
+ if(!raw || !raw->rawdata){
+ free(raw);
+ return NULL;
+ }
+ win->title = strdup(title);
+ win->image = raw;
+ if(pthread_mutex_init(&win->mutex, NULL)){
+ WARN(_("Can't init mutex!"));
+ killwindow();
+ return NULL;
+ }
+ win->w = w;
+ win->h = h;
+ pthread_create(&GLUTthread, NULL, &Redraw, NULL);
+ return win;
+}
+
+/**
+ * Init freeGLUT
+ */
+void imageview_init(){
+ FNAME();
+ char *v[] = {"Image view window", NULL};
+ int c = 1;
+ if(initialized){
+ WARNX(_("Already initialized!"));
+ return;
+ }
+ XInitThreads(); // we need it for threaded windows
+ glutInit(&c, v);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+ glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
+ initialized = 1;
+}
+
+/**
+ * Close all opened windows and terminate main GLUT thread
+ */
+void clear_GL_context(){
+ FNAME();
+ if(!initialized) return;
+ initialized = 0;
+ DBG("kill");
+ killwindow();
+ DBG("join");
+ if(GLUTthread) pthread_join(GLUTthread, NULL); // wait while main thread exits
+ DBG("main GL thread cancelled");
+}
+
+
+/*
+ * Coordinates transformation from CS of drawingArea into CS of picture
+ * x,y - pointer coordinates
+ * X,Y - coordinates of appropriate point at picture
+ */
+void conv_mouse_to_image_coords(int x, int y,
+ float *X, float *Y,
+ windowData *window){
+ float a = window->Daspect / window->zoom;
+ *X = (float)x * a - window->x0;
+ *Y = window->y0 - (float)y * a;
+}
+
+void conv_image_to_mouse_coords(float X, float Y,
+ int *x, int *y,
+ windowData *window){
+ float a = window->zoom / window->Daspect;
+ *x = (int)roundf((X + window->x0) * a);
+ *y = (int)roundf((window->y0 - Y) * a);
+}
+
+
+windowData *getWin(){
+ return win;
+}
+
+/**
+ * Convert gray (unsigned short) into RGB components (GLubyte)
+ * @argument L - gray level (0..1)
+ * @argument rgb - rgb array (GLubyte [3])
+ */
+static void gray2rgb(double gray, GLubyte *rgb){
+ int i = gray * 4.;
+ double x = (gray - (double)i * .25) * 4.;
+ GLubyte r = 0, g = 0, b = 0;
+ //r = g = b = (gray < 1) ? gray * 256 : 255;
+ switch(i){
+ case 0:
+ g = (GLubyte)(255. * x);
+ b = 255;
+ break;
+ case 1:
+ g = 255;
+ b = (GLubyte)(255. * (1. - x));
+ break;
+ case 2:
+ r = (GLubyte)(255. * x);
+ g = 255;
+ break;
+ case 3:
+ r = 255;
+ g = (GLubyte)(255. * (1. - x));
+ break;
+ default:
+ r = 255;
+ }
+ *rgb++ = r;
+ *rgb++ = g;
+ *rgb = b;
+}
+
+typedef enum{
+ COLORFN_LINEAR, // linear
+ COLORFN_LOG, // ln
+ COLORFN_SQRT, // sqrt
+ COLORFN_MAX // end of list
+} colorfn_type;
+
+static colorfn_type ft = COLORFN_LINEAR;
+
+// all colorfun's should get argument in [0, 1] and return in [0, 1]
+static double linfun(double arg){ return arg; } // bung for PREVIEW_LINEAR
+static double logfun(double arg){ return log(1.+arg) / 0.6931472; } // for PREVIEW_LOG [log_2(x+1)]
+static double (*colorfun)(double) = linfun; // default function to convert color
+
+static void change_colorfun(colorfn_type f){
+ DBG("New colorfn: %d", f);
+ switch (f){
+ case COLORFN_LOG:
+ colorfun = logfun;
+ ft = COLORFN_LOG;
+ break;
+ case COLORFN_SQRT:
+ colorfun = sqrt;
+ ft = COLORFN_SQRT;
+ break;
+ default: // linear
+ colorfun = linfun;
+ ft = COLORFN_LINEAR;
+ }
+}
+
+// cycle switch between palettes
+static void roll_colorfun(){
+ colorfn_type t = ++ft;
+ if(t == COLORFN_MAX) t = COLORFN_LINEAR;
+ change_colorfun(t);
+}
+
+/**
+ * @brief equalize - hystogram equalization
+ * @param ori (io) - input/output data
+ * @param w,h - image width and height
+ * @return data allocated here
+ */
+static uint8_t *equalize(uint16_t *ori, int w, int h){
+ uint8_t *retn = MALLOC(uint8_t, w*h);
+ double orig_hysto[0x10000] = {0.}; // original hystogram
+ uint8_t eq_levls[0x10000] = {0}; // levels to convert: newpix = eq_levls[oldpix]
+ int s = w*h;
+ for(int i = 0; i < s; ++i) ++orig_hysto[ori[i]];
+ double part = (double)(s + 1) / 0x100, N = 0.;
+ for(int i = 0; i <= 0xffff; ++i){
+ N += orig_hysto[i];
+ eq_levls[i] = (uint8_t)(N/part);
+ }
+
+ for(int i = 0; i < s; ++i){
+ retn[i] = eq_levls[ori[i]];
+ }
+ return retn;
+}
+
+void change_displayed_image(windowData *win, IMG *img){
+ if(!win || !win->image) return;
+ rawimage *im = win->image;
+ DBG("imh=%d, imw=%d, ch=%u, cw=%u", im->h, im->w, img->w, img->h);
+ pthread_mutex_lock(&win->mutex);
+ int w = img->w, h = img->h, s = w*h;
+ uint8_t *newima = equalize(img->data, w, h);
+ GLubyte *dst = im->rawdata;
+ for(int i = 0; i < s; ++i, dst += 3){
+ gray2rgb(colorfun(newima[i] / 256.), dst);
+ }
+ FREE(newima);
+ win->image->changed = 1;
+ pthread_mutex_unlock(&win->mutex);
+}
+
+void* image_thread(_U_ void *data){
+ FNAME();
+ IMG *img = (IMG*) data;
+ while(1){
+ windowData *win = getWin();
+ if(!win || win->killthread){
+ DBG("got killthread");
+ clear_GL_context();
+ pthread_exit(NULL);
+ }
+ if(win && win->winevt){
+ if(win->winevt & WINEVT_SAVEIMAGE){ // save image
+ verbose(2, "Make screenshot\n");
+ saveImages(img, "ScreenShot");
+ win->winevt &= ~WINEVT_SAVEIMAGE;
+ }
+ if(win->winevt & WINEVT_ROLLCOLORFUN){
+ roll_colorfun();
+ win->winevt &= ~WINEVT_ROLLCOLORFUN;
+ change_displayed_image(win, img);
+ }
+ }
+ usleep(10000);
+ }
+}
diff --git a/fli_control/imageview.h b/fli_control/imageview.h
new file mode 100644
index 0000000..06f4135
--- /dev/null
+++ b/fli_control/imageview.h
@@ -0,0 +1,91 @@
+/*
+ * imageview.h
+ *
+ * Copyright 2015 Edward V. Emelianov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#pragma once
+#ifndef __BMPVIEW_H__
+#define __BMPVIEW_H__
+
+#include
+#include
+#include
+#include
+
+#include "events.h"
+#include "flifunc.h"
+
+typedef struct{
+ GLubyte *rawdata; // raw image data
+ int w; // size of image
+ int h;
+ int changed; // == 1 if data was changed outside (to redraw)
+} rawimage;
+
+// events from menu:
+// temporaly stop capture of regular sequence
+#define WINEVT_PAUSE (1<<0)
+// capture one image in pause mode
+#define WINEVT_GETIMAGE (1<<1)
+// save current image
+#define WINEVT_SAVEIMAGE (1<<2)
+// change color palette function
+#define WINEVT_ROLLCOLORFUN (1<<3)
+
+// flip image
+#define WIN_FLIP_LR (1<<0)
+#define WIN_FLIP_UD (1<<1)
+
+typedef struct{
+ int ID; // identificator of OpenGL window
+ char *title; // title of window
+ GLuint Tex; // texture for image inside window
+ rawimage *image; // raw image data
+ int w; int h; // window size
+ float x; float y; // image offset coordinates
+ float x0; float y0; // center of window for coords conversion
+ float zoom; // zoom aspect
+ float Daspect; // aspect ratio between image & window sizes
+ int menu; // window menu identifier
+ uint32_t winevt; // window menu events
+ uint8_t flip; // flipping settings
+ pthread_t thread; // identificator of thread that changes window data
+ pthread_mutex_t mutex;// mutex for operations with image
+ int killthread; // flag for killing data changing thread & also signal that there's no threads
+} windowData;
+
+typedef enum{
+ INNER,
+ OPENGL
+} winIdType;
+
+void imageview_init();
+windowData *createGLwin(char *title, int w, int h, rawimage *rawdata);
+windowData *getWin();
+int killwindow();
+void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color);
+void clear_GL_context();
+
+void calc_win_props(GLfloat *Wortho, GLfloat *Hortho);
+
+void conv_mouse_to_image_coords(int x, int y, float *X, float *Y, windowData *window);
+void conv_image_to_mouse_coords(float X, float Y, int *x, int *y, windowData *window);
+
+void* image_thread(void *data);
+void change_displayed_image(windowData *win, IMG *img);
+#endif // __BMPVIEW_H__
diff --git a/fli_control/locale/ru/LC_MESSAGES/fli_control.mo b/fli_control/locale/ru/LC_MESSAGES/fli_control.mo
index 1a0f90b..a85c6ae 100644
Binary files a/fli_control/locale/ru/LC_MESSAGES/fli_control.mo and b/fli_control/locale/ru/LC_MESSAGES/fli_control.mo differ
diff --git a/fli_control/locale/ru/messages.po b/fli_control/locale/ru/messages.po
index d8d3b68..c95d548 100644
--- a/fli_control/locale/ru/messages.po
+++ b/fli_control/locale/ru/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-02-22 20:05+0300\n"
+"POT-Creation-Date: 2020-12-07 19:35+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,433 +17,358 @@ msgstr ""
"Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:65
+#: cmdlnopts.c:66
msgid "show this help"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:66
+#: cmdlnopts.c:67
msgid "rewrite output file if exists"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:67
+#: cmdlnopts.c:68
msgid "verbose level (each -v increase it)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:68
+#: cmdlnopts.c:69
msgid "not open shutter, when exposing (\"dark frames\")"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:69
-msgid "open shutter"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:70
-msgid "close shutter"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:71
-msgid "run exposition on LOW @ pin5 I/O port"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:72
-msgid "run exposition on HIGH @ pin5 I/O port"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:73
-msgid "get value of I/O port pins"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:74
-msgid "move stepper motor asynchronous"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:75
+#: cmdlnopts.c:70
msgid "run in 8-bit mode"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:76
+#: cmdlnopts.c:71
msgid "fast (8MHz) readout mode"
msgstr ""
-#. {"", NO_ARGS, NULL, '', arg_int, APTR(&G.), N_("")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:79
+#: cmdlnopts.c:72
+msgid "set CCD temperature to given value (degr C)"
+msgstr ""
+
+#: cmdlnopts.c:74
msgid "program author"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:80
+#: cmdlnopts.c:75
msgid "object type (neon, object, flat etc)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:81
+#: cmdlnopts.c:76
msgid "instrument name"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:82
+#: cmdlnopts.c:77
msgid "object name"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:83
+#: cmdlnopts.c:78
msgid "observers' names"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:84
+#: cmdlnopts.c:79
msgid "observing program name"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:85
+#: cmdlnopts.c:80
msgid "add records to header from given file[s]"
msgstr ""
-#. {"", NEED_ARG, NULL, '', arg_string, APTR(&G.), N_("")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:88
+#: cmdlnopts.c:82
msgid "N flushes before exposing"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:89
+#: cmdlnopts.c:83
msgid "horizontal binning to N pixels"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:90
+#: cmdlnopts.c:84
msgid "vertical binning to N pixels"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:91
+#: cmdlnopts.c:85
msgid "make series of N frames"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:92
+#: cmdlnopts.c:86
msgid "make pause for N seconds between expositions"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:93
+#: cmdlnopts.c:87
msgid "set exposure time to given value (ms)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:94
+#: cmdlnopts.c:88
msgid "frame X0 coordinate (-1 - all with overscan)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:95
+#: cmdlnopts.c:89
msgid "frame Y0 coordinate (-1 - all with overscan)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:96
+#: cmdlnopts.c:90
msgid "frame X1 coordinate (-1 - all with overscan)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:97
+#: cmdlnopts.c:91
msgid "frame Y1 coordinate (-1 - all with overscan)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:98
+#: cmdlnopts.c:93
+msgid "open shutter"
+msgstr ""
+
+#: cmdlnopts.c:94
+msgid "close shutter"
+msgstr ""
+
+#: cmdlnopts.c:95
+msgid "run exposition on LOW @ pin5 I/O port"
+msgstr ""
+
+#: cmdlnopts.c:96
+msgid "run exposition on HIGH @ pin5 I/O port"
+msgstr ""
+
+#: cmdlnopts.c:97
+msgid "get value of I/O port pins"
+msgstr ""
+
+#: cmdlnopts.c:98
+msgid "move stepper motor asynchronous"
+msgstr ""
+
+#: cmdlnopts.c:100
msgid "set I/O port pins to given value (decimal number, pin1 is LSB)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:99
+#: cmdlnopts.c:101
msgid ""
"configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == "
"output, 0 == input)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:100
+#: cmdlnopts.c:103
msgid "move focuser to absolute position"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:101
+#: cmdlnopts.c:104
msgid "move focuser to relative position"
msgstr ""
-#. {"wheel-get",NO_ARGS, NULL, 0, arg_none, APTR(&G.getwheel), N_("get current wheel position")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:103
+#: cmdlnopts.c:106
msgid "set wheel position"
msgstr ""
-#. {"", NEED_ARG, NULL, '', arg_int, APTR(&G.), N_("")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:106
-msgid "set CCD temperature to given value (degr C)"
+#: cmdlnopts.c:109
+msgid "Display image in OpenGL window"
msgstr ""
#. '%s'
-#: /home/eddy/Doc/FLI/fli_control/main.c:130
+#: flifunc.c:123
#, c-format
msgid "Library version '%s'"
msgstr ""
+#. :\n
+#: flifunc.c:188
+#, c-format
+msgid "Image stat:\n"
+msgstr ""
+
#. :\t\t%s
-#: /home/eddy/Doc/FLI/fli_control/main.c:146
-#: /home/eddy/Doc/FLI/fli_control/main.c:237
-#: /home/eddy/Doc/FLI/fli_control/main.c:318
+#: flifunc.c:215 flifunc.c:312 flifunc.c:434
#, c-format
msgid "Model:\t\t%s"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:149
+#: flifunc.c:218
#, c-format
msgid "Focuser '%s', domain %s"
msgstr ""
#. . : %ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:152
-#: /home/eddy/Doc/FLI/fli_control/main.c:240
-#: /home/eddy/Doc/FLI/fli_control/main.c:322
+#: flifunc.c:221 flifunc.c:315 flifunc.c:438
#, c-format
msgid "HW revision: %ld"
msgstr ""
#. . : %ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:155
-#: /home/eddy/Doc/FLI/fli_control/main.c:243
-#: /home/eddy/Doc/FLI/fli_control/main.c:325
+#: flifunc.c:224 flifunc.c:318 flifunc.c:441
#, c-format
msgid "SW revision: %ld"
msgstr ""
#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:171
+#: flifunc.c:240
msgid "You can't use both relative and absolute position"
msgstr ""
#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:176
+#: flifunc.c:245
msgid "Error in position detection"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:188
+#: flifunc.c:257
msgid "Already at position"
msgstr ""
#. 0...%ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:193
+#: flifunc.c:262
#, c-format
msgid "Position should be in 0...%ld"
msgstr ""
#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:198
+#: flifunc.c:267
msgid "Moving to home position"
msgstr ""
#. %ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:203
+#: flifunc.c:272
#, c-format
msgid "Moving for %ld steps"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:215
+#: flifunc.c:284
msgid "No focusers found"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:232
+#: flifunc.c:307
#, c-format
msgid "Wheel '%s', domain %s"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:247
+#: flifunc.c:322
#, c-format
msgid "Wheel position should be from 0 to %ld"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:271
+#: flifunc.c:328
#, c-format
msgid "Position is too big (max %d)"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:275
+#: flifunc.c:332
msgid "Arrive to position"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:299
+#: flifunc.c:356
msgid "No wheels found"
msgstr ""
-#: /home/eddy/Doc/FLI/fli_control/main.c:307
-msgid "No CCD found"
-msgstr ""
-
-#. '%s' %s
-#: /home/eddy/Doc/FLI/fli_control/main.c:313
-#, c-format
-msgid "Camera '%s', domain %s"
-msgstr ""
-
-#. : %g x %g
-#: /home/eddy/Doc/FLI/fli_control/main.c:328
-#, c-format
-msgid "Pixel size: %g x %g"
-msgstr ""
-
-#. : %s
-#: /home/eddy/Doc/FLI/fli_control/main.c:332
-#, c-format
-msgid "Field of view: %s"
-msgstr ""
-
-#. : (%ld, %ld)(%ld, %ld)
-#: /home/eddy/Doc/FLI/fli_control/main.c:337
-#, c-format
-msgid "Array field: (%ld, %ld)(%ld, %ld)"
-msgstr ""
-
-#. " : %g \n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:351
-#, c-format
-msgid "Set CCD temperature to %g degr.C\n"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/main.c:377
-#, c-format
-msgid "%s CCD shutter\n"
-msgstr ""
-
-#. " I/O %d\n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:388
-#, c-format
-msgid "Try to convfigure I/O port as %d\n"
-msgstr ""
-
-#. " %d I/O\n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:398
-#, c-format
-msgid "Try to write %d to I/O port\n"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/main.c:419
-msgid "8 bit mode\n"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/main.c:422
-msgid "Fast readout mode\n"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/main.c:423
-msgid "Only show statistics\n"
-msgstr ""
-
-#. %d\n
-#: /home/eddy/Doc/FLI/fli_control/main.c:429
-#, c-format
-msgid "Capture frame %d\n"
-msgstr ""
-
#. /
-#: /home/eddy/Doc/FLI/fli_control/main.c:437
-#: /home/eddy/Doc/FLI/fli_control/main.c:501
+#: flifunc.c:378 flifunc.c:565
msgid "date/time"
msgstr ""
#. " "
-#: /home/eddy/Doc/FLI/fli_control/main.c:444
+#: flifunc.c:385
#, c-format
msgid "wait for external trigger...\n"
msgstr ""
#. %.3f \n
-#: /home/eddy/Doc/FLI/fli_control/main.c:448
+#: flifunc.c:389
#, c-format
msgid "%.3f seconds till exposition ends\n"
msgstr ""
#. :
-#: /home/eddy/Doc/FLI/fli_control/main.c:454
+#: flifunc.c:395
#, c-format
msgid "Read image: "
msgstr ""
-#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:473
-msgid "Can't save file"
+#: flifunc.c:425
+msgid "No CCD found"
msgstr ""
-#. '%s'
-#: /home/eddy/Doc/FLI/fli_control/main.c:482
+#. '%s' %s
+#: flifunc.c:429
#, c-format
-msgid "File saved as '%s'"
+msgid "Camera '%s', domain %s"
+msgstr ""
+
+#. : %g x %g
+#: flifunc.c:444
+#, c-format
+msgid "Pixel size: %g x %g"
+msgstr ""
+
+#. : %s
+#: flifunc.c:448
+#, c-format
+msgid "Field of view: %s"
+msgstr ""
+
+#. : (%ld, %ld)(%ld, %ld)
+#: flifunc.c:453
+#, c-format
+msgid "Array field: (%ld, %ld)(%ld, %ld)"
+msgstr ""
+
+#. " : %g \n"
+#: flifunc.c:467
+#, c-format
+msgid "Set CCD temperature to %g degr.C\n"
+msgstr ""
+
+#: flifunc.c:493
+#, c-format
+msgid "%s CCD shutter\n"
+msgstr ""
+
+#. " I/O %d\n"
+#: flifunc.c:498
+#, c-format
+msgid "Try to convfigure I/O port as %d\n"
+msgstr ""
+
+#. " %d I/O\n"
+#: flifunc.c:508
+#, c-format
+msgid "Try to write %d to I/O port\n"
+msgstr ""
+
+#: flifunc.c:518
+msgid "8 bit mode\n"
+msgstr ""
+
+#: flifunc.c:521
+msgid "Fast readout mode\n"
+msgstr ""
+
+#: flifunc.c:522
+msgid "Only show statistics\n"
+msgstr ""
+
+#. %d\n
+#: flifunc.c:528
+#, c-format
+msgid "Capture frame %d\n"
msgstr ""
#. %d \n
-#: /home/eddy/Doc/FLI/fli_control/main.c:496
+#: flifunc.c:560
#, c-format
msgid "%d seconds till pause ends\n"
msgstr ""
-#. :\n
-#: /home/eddy/Doc/FLI/fli_control/main.c:770
+#.
+#: flifunc.c:605
+msgid "Can't save file"
+msgstr ""
+
+#. '%s'
+#: flifunc.c:615
#, c-format
-msgid "Image stat:\n"
+msgid "File saved as '%s'"
msgstr ""
-#. amount of pcount and/or scount wrong
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:56
-msgid "Wrong helpstring!"
+#: imageview.c:257
+msgid "Can't init mutex!"
msgstr ""
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:86
-msgid "Integer out of range"
-msgstr ""
-
-#. / " : %s"
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:480
-#, c-format
-msgid "Wrong parameter: %s"
-msgstr ""
-
-#. / "%s: !"
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:485
-#, c-format
-msgid "%s: argument needed!"
-msgstr ""
-
-#. / " \"%s\" \"%s\""
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:490
-#, c-format
-msgid "Wrong argument \"%s\" of parameter \"%s\""
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:173
-msgid "No filename given!"
-msgstr ""
-
-#. / " %s "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:178
-#, c-format
-msgid "Can't open %s for reading"
-msgstr ""
-
-#. / " stat %s"
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:183
-#, c-format
-msgid "Can't stat %s"
-msgstr ""
-
-#. / " mmap"
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:190
-msgid "Mmap error for input"
-msgstr ""
-
-#. / " mmap' "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:195
-msgid "Can't close mmap'ed file"
-msgstr ""
-
-#. / " munmap"
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:205
-msgid "Can't munmap"
-msgstr ""
-
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:231
-msgid "Can't setup console"
-msgstr ""
-
-#. Get settings
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:301
-msgid "Can't get settings"
-msgstr ""
-
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:312
-msgid "Can't set settings"
+#: imageview.c:275
+msgid "Already initialized!"
msgstr ""
diff --git a/fli_control/locale/ru/ru.po b/fli_control/locale/ru/ru.po
index f3f8747..11e70f5 100644
--- a/fli_control/locale/ru/ru.po
+++ b/fli_control/locale/ru/ru.po
@@ -7,7 +7,7 @@
msgid ""
msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2020-02-22 20:05+0300\n"
+ "POT-Creation-Date: 2020-12-07 19:35+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,431 +17,356 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Content-Transfer-Encoding: 8bit\n"
#. %.3f \n
-#: /home/eddy/Doc/FLI/fli_control/main.c:448
+#: flifunc.c:389
#, c-format
msgid "%.3f seconds till exposition ends\n"
-msgstr ""
+msgstr "%.3f \n"
#. %d \n
-#: /home/eddy/Doc/FLI/fli_control/main.c:496
+#: flifunc.c:560
#, c-format
msgid "%d seconds till pause ends\n"
-msgstr ""
+msgstr "%d \n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:377
+#: flifunc.c:493
#, c-format
msgid "%s CCD shutter\n"
-msgstr ""
+msgstr "%s \n"
-#. / "%s: !"
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:485
-#, c-format
-msgid "%s: argument needed!"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/main.c:419
+#: flifunc.c:518
msgid "8 bit mode\n"
-msgstr ""
+msgstr " 8 \n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:188
+#: flifunc.c:257
msgid "Already at position"
-msgstr ""
+msgstr " "
+
+#: imageview.c:275
+msgid "Already initialized!"
+msgstr " !"
#. : (%ld, %ld)(%ld, %ld)
-#: /home/eddy/Doc/FLI/fli_control/main.c:337
+#: flifunc.c:453
#, c-format
msgid "Array field: (%ld, %ld)(%ld, %ld)"
-msgstr ""
+msgstr " : (%ld, %ld)(%ld, %ld)"
-#: /home/eddy/Doc/FLI/fli_control/main.c:275
+#: flifunc.c:332
msgid "Arrive to position"
-msgstr ""
+msgstr " "
#. '%s' %s
-#: /home/eddy/Doc/FLI/fli_control/main.c:313
+#: flifunc.c:429
#, c-format
msgid "Camera '%s', domain %s"
-msgstr ""
+msgstr " '%s' %s"
-#. / " mmap' "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:195
-msgid "Can't close mmap'ed file"
-msgstr ""
-
-#. Get settings
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:301
-msgid "Can't get settings"
-msgstr ""
-
-#. / " munmap"
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:205
-msgid "Can't munmap"
-msgstr ""
-
-#. / " %s "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:178
-#, c-format
-msgid "Can't open %s for reading"
-msgstr ""
+#: imageview.c:257
+msgid "Can't init mutex!"
+msgstr " !"
#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:473
+#: flifunc.c:605
msgid "Can't save file"
-msgstr ""
-
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:312
-msgid "Can't set settings"
-msgstr ""
-
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:231
-msgid "Can't setup console"
-msgstr ""
-
-#. / " stat %s"
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:183
-#, c-format
-msgid "Can't stat %s"
-msgstr ""
+msgstr " "
#. %d\n
-#: /home/eddy/Doc/FLI/fli_control/main.c:429
+#: flifunc.c:528
#, c-format
msgid "Capture frame %d\n"
-msgstr ""
+msgstr " %d\n"
+
+#: cmdlnopts.c:109
+msgid "Display image in OpenGL window"
+msgstr " OpenGL"
#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:176
+#: flifunc.c:245
msgid "Error in position detection"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/main.c:422
+#: flifunc.c:521
msgid "Fast readout mode\n"
-msgstr ""
+msgstr " \n"
#. : %s
-#: /home/eddy/Doc/FLI/fli_control/main.c:332
+#: flifunc.c:448
#, c-format
msgid "Field of view: %s"
-msgstr ""
+msgstr " : %s"
#. '%s'
-#: /home/eddy/Doc/FLI/fli_control/main.c:482
+#: flifunc.c:615
#, c-format
msgid "File saved as '%s'"
-msgstr ""
+msgstr " '%s'"
-#: /home/eddy/Doc/FLI/fli_control/main.c:149
+#: flifunc.c:218
#, c-format
msgid "Focuser '%s', domain %s"
-msgstr ""
+msgstr " '%s', %s"
#. . : %ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:152
-#: /home/eddy/Doc/FLI/fli_control/main.c:240
-#: /home/eddy/Doc/FLI/fli_control/main.c:322
+#: flifunc.c:221 flifunc.c:315 flifunc.c:438
#, c-format
msgid "HW revision: %ld"
-msgstr ""
+msgstr ". : %ld"
#. :\n
-#: /home/eddy/Doc/FLI/fli_control/main.c:770
+#: flifunc.c:188
#, c-format
msgid "Image stat:\n"
-msgstr ""
-
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:86
-msgid "Integer out of range"
-msgstr ""
+msgstr " :\n"
#. '%s'
-#: /home/eddy/Doc/FLI/fli_control/main.c:130
+#: flifunc.c:123
#, c-format
msgid "Library version '%s'"
-msgstr ""
-
-#. / " mmap"
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:190
-msgid "Mmap error for input"
-msgstr ""
+msgstr " '%s'"
#. :\t\t%s
-#: /home/eddy/Doc/FLI/fli_control/main.c:146
-#: /home/eddy/Doc/FLI/fli_control/main.c:237
-#: /home/eddy/Doc/FLI/fli_control/main.c:318
+#: flifunc.c:215 flifunc.c:312 flifunc.c:434
#, c-format
msgid "Model:\t\t%s"
-msgstr ""
+msgstr ":\t\t%s"
#. %ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:203
+#: flifunc.c:272
#, c-format
msgid "Moving for %ld steps"
-msgstr ""
+msgstr " %ld "
#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:198
+#: flifunc.c:267
msgid "Moving to home position"
-msgstr ""
+msgstr " "
-#. {"", NEED_ARG, NULL, '', arg_string, APTR(&G.), N_("")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:88
+#: cmdlnopts.c:82
msgid "N flushes before exposing"
-msgstr ""
+msgstr "N "
-#: /home/eddy/Doc/FLI/fli_control/main.c:307
+#: flifunc.c:425
msgid "No CCD found"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/usefull_macros.c:173
-msgid "No filename given!"
-msgstr ""
-
-#: /home/eddy/Doc/FLI/fli_control/main.c:215
+#: flifunc.c:284
msgid "No focusers found"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/main.c:299
+#: flifunc.c:356
msgid "No wheels found"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/main.c:423
+#: flifunc.c:522
msgid "Only show statistics\n"
-msgstr ""
+msgstr " \n"
#. : %g x %g
-#: /home/eddy/Doc/FLI/fli_control/main.c:328
+#: flifunc.c:444
#, c-format
msgid "Pixel size: %g x %g"
-msgstr ""
+msgstr " : %g x %g"
-#: /home/eddy/Doc/FLI/fli_control/main.c:271
+#: flifunc.c:328
#, c-format
msgid "Position is too big (max %d)"
-msgstr ""
+msgstr " (. %d)"
#. 0...%ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:193
+#: flifunc.c:262
#, c-format
msgid "Position should be in 0...%ld"
-msgstr ""
+msgstr " 0...%ld"
#. :
-#: /home/eddy/Doc/FLI/fli_control/main.c:454
+#: flifunc.c:395
#, c-format
msgid "Read image: "
-msgstr ""
+msgstr " :"
#. . : %ld
-#: /home/eddy/Doc/FLI/fli_control/main.c:155
-#: /home/eddy/Doc/FLI/fli_control/main.c:243
-#: /home/eddy/Doc/FLI/fli_control/main.c:325
+#: flifunc.c:224 flifunc.c:318 flifunc.c:441
#, c-format
msgid "SW revision: %ld"
-msgstr ""
+msgstr ". : %ld"
#. " : %g \n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:351
+#: flifunc.c:467
#, c-format
msgid "Set CCD temperature to %g degr.C\n"
-msgstr ""
+msgstr " : %g \n"
#. " I/O %d\n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:388
+#: flifunc.c:498
#, c-format
msgid "Try to convfigure I/O port as %d\n"
-msgstr ""
+msgstr " I/O %d\n"
#. " %d I/O\n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:398
+#: flifunc.c:508
#, c-format
msgid "Try to write %d to I/O port\n"
-msgstr ""
+msgstr " %d I/O\n"
-#: /home/eddy/Doc/FLI/fli_control/main.c:232
+#: flifunc.c:307
#, c-format
msgid "Wheel '%s', domain %s"
-msgstr ""
+msgstr " '%s', %s"
-#: /home/eddy/Doc/FLI/fli_control/main.c:247
+#: flifunc.c:322
#, c-format
msgid "Wheel position should be from 0 to %ld"
-msgstr ""
-
-#. / " \"%s\" \"%s\""
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:490
-#, c-format
-msgid "Wrong argument \"%s\" of parameter \"%s\""
-msgstr ""
-
-#. amount of pcount and/or scount wrong
-#. / " "
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:56
-msgid "Wrong helpstring!"
-msgstr ""
-
-#. / " : %s"
-#: /home/eddy/Doc/FLI/fli_control/parseargs.c:480
-#, c-format
-msgid "Wrong parameter: %s"
-msgstr ""
+msgstr " 0 %ld"
#.
-#: /home/eddy/Doc/FLI/fli_control/main.c:171
+#: flifunc.c:240
msgid "You can't use both relative and absolute position"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:85
+#: cmdlnopts.c:80
msgid "add records to header from given file[s]"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:70
+#: cmdlnopts.c:94
msgid "close shutter"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:99
+#: cmdlnopts.c:101
msgid "configure I/O port pins to given value (decimal number, pin1 is LSB, "
"1 == output, 0 == input)"
-msgstr ""
+msgstr " / ( , 1 - , 1 - , 0 - )"
#. /
-#: /home/eddy/Doc/FLI/fli_control/main.c:437
-#: /home/eddy/Doc/FLI/fli_control/main.c:501
+#: flifunc.c:378 flifunc.c:565
msgid "date/time"
-msgstr ""
+msgstr "/"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:76
+#: cmdlnopts.c:71
msgid "fast (8MHz) readout mode"
-msgstr ""
+msgstr " (8) "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:94
+#: cmdlnopts.c:88
msgid "frame X0 coordinate (-1 - all with overscan)"
-msgstr ""
+msgstr " X0 (-1 - )"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:96
+#: cmdlnopts.c:90
msgid "frame X1 coordinate (-1 - all with overscan)"
-msgstr ""
+msgstr " X1 (-1 - )"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:95
+#: cmdlnopts.c:89
msgid "frame Y0 coordinate (-1 - all with overscan)"
-msgstr ""
+msgstr " Y0 (-1 - )"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:97
+#: cmdlnopts.c:91
msgid "frame Y1 coordinate (-1 - all with overscan)"
-msgstr ""
+msgstr " Y1 (-1 - )"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:73
+#: cmdlnopts.c:97
msgid "get value of I/O port pins"
-msgstr ""
+msgstr " /"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:89
+#: cmdlnopts.c:83
msgid "horizontal binning to N pixels"
-msgstr ""
+msgstr " N "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:81
+#: cmdlnopts.c:76
msgid "instrument name"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:92
+#: cmdlnopts.c:86
msgid "make pause for N seconds between expositions"
-msgstr ""
+msgstr " N "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:91
+#: cmdlnopts.c:85
msgid "make series of N frames"
-msgstr ""
+msgstr " N "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:100
+#: cmdlnopts.c:103
msgid "move focuser to absolute position"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:101
+#: cmdlnopts.c:104
msgid "move focuser to relative position"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:74
+#: cmdlnopts.c:98
msgid "move stepper motor asynchronous"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:68
+#: cmdlnopts.c:69
msgid "not open shutter, when exposing (\"dark frames\")"
-msgstr ""
+msgstr " (\"\")"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:82
+#: cmdlnopts.c:77
msgid "object name"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:80
+#: cmdlnopts.c:75
msgid "object type (neon, object, flat etc)"
-msgstr ""
+msgstr " (neon, object, flat ..)"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:83
+#: cmdlnopts.c:78
msgid "observers' names"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:84
+#: cmdlnopts.c:79
msgid "observing program name"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:69
+#: cmdlnopts.c:93
msgid "open shutter"
-msgstr ""
+msgstr " "
-#. {"", NO_ARGS, NULL, '', arg_int, APTR(&G.), N_("")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:79
+#: cmdlnopts.c:74
msgid "program author"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:66
+#: cmdlnopts.c:67
msgid "rewrite output file if exists"
-msgstr ""
+msgstr " , "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:72
+#: cmdlnopts.c:96
msgid "run exposition on HIGH @ pin5 I/O port"
-msgstr ""
+msgstr " 5"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:71
+#: cmdlnopts.c:95
msgid "run exposition on LOW @ pin5 I/O port"
-msgstr ""
+msgstr " 5"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:75
+#: cmdlnopts.c:70
msgid "run in 8-bit mode"
-msgstr ""
+msgstr "8- "
-#. {"", NEED_ARG, NULL, '', arg_int, APTR(&G.), N_("")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:106
+#: cmdlnopts.c:72
msgid "set CCD temperature to given value (degr C)"
-msgstr ""
+msgstr " ( )"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:98
+#: cmdlnopts.c:100
msgid "set I/O port pins to given value (decimal number, pin1 is LSB)"
-msgstr ""
+msgstr " - ( , pin1 )"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:93
+#: cmdlnopts.c:87
msgid "set exposure time to given value (ms)"
-msgstr ""
+msgstr " ()"
-#. {"wheel-get",NO_ARGS, NULL, 0, arg_none, APTR(&G.getwheel), N_("get current wheel position")},
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:103
+#: cmdlnopts.c:106
msgid "set wheel position"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:65
+#: cmdlnopts.c:66
msgid "show this help"
-msgstr ""
+msgstr " "
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:67
+#: cmdlnopts.c:68
msgid "verbose level (each -v increase it)"
-msgstr ""
+msgstr " ( -V )"
-#: /home/eddy/Doc/FLI/fli_control/cmdlnopts.c:90
+#: cmdlnopts.c:84
msgid "vertical binning to N pixels"
-msgstr ""
+msgstr " N "
#. " "
-#: /home/eddy/Doc/FLI/fli_control/main.c:444
+#: flifunc.c:385
#, c-format
msgid "wait for external trigger...\n"
-msgstr ""
+msgstr " ...\n"
diff --git a/fli_control/locale/ru/ru.po.bkp b/fli_control/locale/ru/ru.po.bkp
new file mode 100644
index 0000000..11e70f5
--- /dev/null
+++ b/fli_control/locale/ru/ru.po.bkp
@@ -0,0 +1,372 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr "Project-Id-Version: PACKAGE VERSION\n"
+ "Report-Msgid-Bugs-To: \n"
+ "POT-Creation-Date: 2020-12-07 19:35+0300\n"
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+ "Last-Translator: FULL NAME \n"
+ "Language-Team: LANGUAGE \n"
+ "Language: \n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=koi8-r\n"
+ "Content-Transfer-Encoding: 8bit\n"
+
+#. %.3f \n
+#: flifunc.c:389
+#, c-format
+msgid "%.3f seconds till exposition ends\n"
+msgstr "%.3f \n"
+
+#. %d \n
+#: flifunc.c:560
+#, c-format
+msgid "%d seconds till pause ends\n"
+msgstr "%d \n"
+
+#: flifunc.c:493
+#, c-format
+msgid "%s CCD shutter\n"
+msgstr "%s \n"
+
+#: flifunc.c:518
+msgid "8 bit mode\n"
+msgstr " 8 \n"
+
+#: flifunc.c:257
+msgid "Already at position"
+msgstr " "
+
+#: imageview.c:275
+msgid "Already initialized!"
+msgstr " !"
+
+#. : (%ld, %ld)(%ld, %ld)
+#: flifunc.c:453
+#, c-format
+msgid "Array field: (%ld, %ld)(%ld, %ld)"
+msgstr " : (%ld, %ld)(%ld, %ld)"
+
+#: flifunc.c:332
+msgid "Arrive to position"
+msgstr " "
+
+#. '%s' %s
+#: flifunc.c:429
+#, c-format
+msgid "Camera '%s', domain %s"
+msgstr " '%s' %s"
+
+#: imageview.c:257
+msgid "Can't init mutex!"
+msgstr " !"
+
+#.
+#: flifunc.c:605
+msgid "Can't save file"
+msgstr " "
+
+#. %d\n
+#: flifunc.c:528
+#, c-format
+msgid "Capture frame %d\n"
+msgstr " %d\n"
+
+#: cmdlnopts.c:109
+msgid "Display image in OpenGL window"
+msgstr " OpenGL"
+
+#.
+#: flifunc.c:245
+msgid "Error in position detection"
+msgstr " "
+
+#: flifunc.c:521
+msgid "Fast readout mode\n"
+msgstr " \n"
+
+#. : %s
+#: flifunc.c:448
+#, c-format
+msgid "Field of view: %s"
+msgstr " : %s"
+
+#. '%s'
+#: flifunc.c:615
+#, c-format
+msgid "File saved as '%s'"
+msgstr " '%s'"
+
+#: flifunc.c:218
+#, c-format
+msgid "Focuser '%s', domain %s"
+msgstr " '%s', %s"
+
+#. . : %ld
+#: flifunc.c:221 flifunc.c:315 flifunc.c:438
+#, c-format
+msgid "HW revision: %ld"
+msgstr ". : %ld"
+
+#. :\n
+#: flifunc.c:188
+#, c-format
+msgid "Image stat:\n"
+msgstr " :\n"
+
+#. '%s'
+#: flifunc.c:123
+#, c-format
+msgid "Library version '%s'"
+msgstr " '%s'"
+
+#. :\t\t%s
+#: flifunc.c:215 flifunc.c:312 flifunc.c:434
+#, c-format
+msgid "Model:\t\t%s"
+msgstr ":\t\t%s"
+
+#. %ld
+#: flifunc.c:272
+#, c-format
+msgid "Moving for %ld steps"
+msgstr " %ld "
+
+#.
+#: flifunc.c:267
+msgid "Moving to home position"
+msgstr " "
+
+#: cmdlnopts.c:82
+msgid "N flushes before exposing"
+msgstr "N "
+
+#: flifunc.c:425
+msgid "No CCD found"
+msgstr " "
+
+#: flifunc.c:284
+msgid "No focusers found"
+msgstr " "
+
+#: flifunc.c:356
+msgid "No wheels found"
+msgstr " "
+
+#: flifunc.c:522
+msgid "Only show statistics\n"
+msgstr " \n"
+
+#. : %g x %g
+#: flifunc.c:444
+#, c-format
+msgid "Pixel size: %g x %g"
+msgstr " : %g x %g"
+
+#: flifunc.c:328
+#, c-format
+msgid "Position is too big (max %d)"
+msgstr " (. %d)"
+
+#. 0...%ld
+#: flifunc.c:262
+#, c-format
+msgid "Position should be in 0...%ld"
+msgstr " 0...%ld"
+
+#. :
+#: flifunc.c:395
+#, c-format
+msgid "Read image: "
+msgstr " :"
+
+#. . : %ld
+#: flifunc.c:224 flifunc.c:318 flifunc.c:441
+#, c-format
+msgid "SW revision: %ld"
+msgstr ". : %ld"
+
+#. " : %g \n"
+#: flifunc.c:467
+#, c-format
+msgid "Set CCD temperature to %g degr.C\n"
+msgstr " : %g \n"
+
+#. " I/O %d\n"
+#: flifunc.c:498
+#, c-format
+msgid "Try to convfigure I/O port as %d\n"
+msgstr " I/O %d\n"
+
+#. " %d I/O\n"
+#: flifunc.c:508
+#, c-format
+msgid "Try to write %d to I/O port\n"
+msgstr " %d I/O\n"
+
+#: flifunc.c:307
+#, c-format
+msgid "Wheel '%s', domain %s"
+msgstr " '%s', %s"
+
+#: flifunc.c:322
+#, c-format
+msgid "Wheel position should be from 0 to %ld"
+msgstr " 0 %ld"
+
+#.
+#: flifunc.c:240
+msgid "You can't use both relative and absolute position"
+msgstr " "
+
+#: cmdlnopts.c:80
+msgid "add records to header from given file[s]"
+msgstr " "
+
+#: cmdlnopts.c:94
+msgid "close shutter"
+msgstr " "
+
+#: cmdlnopts.c:101
+msgid "configure I/O port pins to given value (decimal number, pin1 is LSB, "
+ "1 == output, 0 == input)"
+msgstr " / ( , 1 - , 1 - , 0 - )"
+
+#. /
+#: flifunc.c:378 flifunc.c:565
+msgid "date/time"
+msgstr "/"
+
+#: cmdlnopts.c:71
+msgid "fast (8MHz) readout mode"
+msgstr " (8) "
+
+#: cmdlnopts.c:88
+msgid "frame X0 coordinate (-1 - all with overscan)"
+msgstr " X0 (-1 - )"
+
+#: cmdlnopts.c:90
+msgid "frame X1 coordinate (-1 - all with overscan)"
+msgstr " X1 (-1 - )"
+
+#: cmdlnopts.c:89
+msgid "frame Y0 coordinate (-1 - all with overscan)"
+msgstr " Y0 (-1 - )"
+
+#: cmdlnopts.c:91
+msgid "frame Y1 coordinate (-1 - all with overscan)"
+msgstr " Y1 (-1 - )"
+
+#: cmdlnopts.c:97
+msgid "get value of I/O port pins"
+msgstr " /"
+
+#: cmdlnopts.c:83
+msgid "horizontal binning to N pixels"
+msgstr " N "
+
+#: cmdlnopts.c:76
+msgid "instrument name"
+msgstr " "
+
+#: cmdlnopts.c:86
+msgid "make pause for N seconds between expositions"
+msgstr " N "
+
+#: cmdlnopts.c:85
+msgid "make series of N frames"
+msgstr " N "
+
+#: cmdlnopts.c:103
+msgid "move focuser to absolute position"
+msgstr " "
+
+#: cmdlnopts.c:104
+msgid "move focuser to relative position"
+msgstr " "
+
+#: cmdlnopts.c:98
+msgid "move stepper motor asynchronous"
+msgstr " "
+
+#: cmdlnopts.c:69
+msgid "not open shutter, when exposing (\"dark frames\")"
+msgstr " (\"\")"
+
+#: cmdlnopts.c:77
+msgid "object name"
+msgstr " "
+
+#: cmdlnopts.c:75
+msgid "object type (neon, object, flat etc)"
+msgstr " (neon, object, flat ..)"
+
+#: cmdlnopts.c:78
+msgid "observers' names"
+msgstr " "
+
+#: cmdlnopts.c:79
+msgid "observing program name"
+msgstr " "
+
+#: cmdlnopts.c:93
+msgid "open shutter"
+msgstr " "
+
+#: cmdlnopts.c:74
+msgid "program author"
+msgstr " "
+
+#: cmdlnopts.c:67
+msgid "rewrite output file if exists"
+msgstr " , "
+
+#: cmdlnopts.c:96
+msgid "run exposition on HIGH @ pin5 I/O port"
+msgstr " 5"
+
+#: cmdlnopts.c:95
+msgid "run exposition on LOW @ pin5 I/O port"
+msgstr " 5"
+
+#: cmdlnopts.c:70
+msgid "run in 8-bit mode"
+msgstr "8- "
+
+#: cmdlnopts.c:72
+msgid "set CCD temperature to given value (degr C)"
+msgstr " ( )"
+
+#: cmdlnopts.c:100
+msgid "set I/O port pins to given value (decimal number, pin1 is LSB)"
+msgstr " - ( , pin1 )"
+
+#: cmdlnopts.c:87
+msgid "set exposure time to given value (ms)"
+msgstr " ()"
+
+#: cmdlnopts.c:106
+msgid "set wheel position"
+msgstr " "
+
+#: cmdlnopts.c:66
+msgid "show this help"
+msgstr " "
+
+#: cmdlnopts.c:68
+msgid "verbose level (each -v increase it)"
+msgstr " ( -V )"
+
+#: cmdlnopts.c:84
+msgid "vertical binning to N pixels"
+msgstr " N "
+
+#. " "
+#: flifunc.c:385
+#, c-format
+msgid "wait for external trigger...\n"
+msgstr " ...\n"
diff --git a/fli_control/main.c b/fli_control/main.c
index 184937d..0d88bf4 100644
--- a/fli_control/main.c
+++ b/fli_control/main.c
@@ -21,755 +21,33 @@
*
*/
-// for strcasestr
-#define _GNU_SOURCE
+#include
#include
-
-#include
#include
#include
#include
#include
-#include
-#include
+#include
-#include "main.h"
-
-#ifndef FLIUSB_VENDORID
-#define FLIUSB_VENDORID 0xf18
+#include "cmdlnopts.h"
+#include "flifunc.h"
+#ifdef IMAGEVIEW
+#include "imageview.h"
#endif
-#ifndef FLIUSB_PROLINE_ID
-#define FLIUSB_PROLINE_ID 0x0a
-#endif
-#ifndef FLIUSB_FILTER_ID
-#define FLIUSB_FILTER_ID 0x07
-#endif
-#ifndef FLIUSB_FOCUSER_ID
-#define FLIUSB_FOCUSER_ID 0x06
-#endif
-
-static long fli_err;
-#define TRYFUNC(f, ...) \
-do{ if((fli_err = f(__VA_ARGS__))) \
- WARNX(#f "() failed"); \
-}while(0)
-
-#ifdef USEPNG
-int writepng(char *filename, int width, int height, void *data);
-#endif /* USEPNG */
-
-#define BUFF_SIZ 4096
-
-#define TMBUFSIZ 40
-static char tm_buf[TMBUFSIZ]; // buffer for string with time value
-
-static glob_pars *G = NULL; // default parameters see in cmdlnopts.c
-
-static uint16_t max = 0, min = 65535; // max/min values for given image
-static double avr, std; // stat values
-static char *camera = NULL, viewfield[80];
-static double pixX, pixY; // pixel size in um
-
-static void print_stat(u_int16_t *img, long size);
-
-static size_t curtime(char *s_time){ // current date/time
- time_t tm = time(NULL);
- return strftime(s_time, TMBUFSIZ, "%d/%m/%Y,%H:%M:%S", localtime(&tm));
-}
-
-static fliframe_t frametype = FLI_FRAME_TYPE_NORMAL;
-static double t_ext, t_int; // external & CCD temperatures @exp. end
-static time_t expStartsAt; // exposition start time (time_t)
-
-static long filterpos = -1; // filter position
-static long focuserpos = -1; // focuser position
-
-static int check_filename(char *buff, char *outfile, char *ext){
- struct stat filestat;
- int num;
- for(num = 1; num < 10000; num++){
- if(snprintf(buff, BUFF_SIZ, "%s_%04d.%s", outfile, num, ext) < 1)
- return 0;
- if(stat(buff, &filestat)) // no such file or can't stat()
- return 1;
- }
- return 0;
-}
void signals(int signo){
exit(signo);
}
extern const char *__progname;
-static void info(const char *fmt, ...){
- va_list ar;
- if(!verbose) return;
- printf("%s: ", __progname);
- va_start(ar, fmt);
- vprintf(fmt, ar);
- va_end(ar);
- printf("\n");
-}
int main(int argc, char **argv){
- int i, num;
- long ltmp;
- char libver[LIBVERSIZ]; // FLI library version
- cam_t *cam = NULL; // list of CCDs available
- flidev_t dev;
- char buff[BUFF_SIZ];
initial_setup();
- G = parse_args(argc, argv);
- // #ifdef EBUG
- TRYFUNC(FLISetDebugLevel, NULL /* "NO HOST" */, FLIDEBUG_NONE);
- /* #else
- TRYFUNC(FLISetDebugLevel, NULL, FLIDEBUG_NONE);
- #endif */
- TRYFUNC(FLIGetLibVersion, libver, LIBVERSIZ);
- // '%s'
- if(!fli_err) info(_("Library version '%s'"), libver);
- /*
- * Find focusers and work with each of them
- */
- num = findcams(FLIDOMAIN_USB | FLIDEVICE_FOCUSER, &cam);
- int nfocs = 0;
- for (i = 0; i < num; i++){
- TRYFUNC(FLIOpen, &dev, cam[i].name, cam[i].domain);
- if(fli_err) continue;
- TRYFUNC(FLIGetModel, dev, buff, BUFF_SIZ);
- if(!fli_err){
- if(!strcasestr(buff, "focuser")){ // not focuser
- TRYFUNC(FLIClose, dev);
- continue;
- }
- // :\t\t%s
- info(_("Model:\t\t%s"), buff);
- }
- ++nfocs;
- info(_("Focuser '%s', domain %s"), cam[i].name, cam[i].dname);
- TRYFUNC(FLIGetHWRevision, dev, <mp);
- // . : %ld
- if(!fli_err) info(_("HW revision: %ld"), ltmp);
- TRYFUNC(FLIGetFWRevision, dev, <mp);
- // . : %ld
- if(!fli_err) info(_("SW revision: %ld"), ltmp);
- TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_INTERNAL, &t_ext);
- if(!fli_err) green("FOCTEMP=%.1f\n", t_ext);
- long curpos = -1, maxpos = -1;
- TRYFUNC(FLIGetStepperPosition, dev, <mp);
- if(!fli_err){
- curpos = ltmp;
- }
- TRYFUNC(FLIGetFocuserExtent, dev, <mp);
- if(!fli_err){
- green("FOCMAXPOS=%ld\n", ltmp);
- maxpos = ltmp;
- }
- do{
- if(G->gotopos != INT_MAX && G->addsteps != INT_MAX){
- //
- WARNX(_("You can't use both relative and absolute position"));
- break;
- }
- if(curpos < 0 || maxpos < 0){
- //
- WARNX(_("Error in position detection"));
- break;
- }
- long pos = -1, steps = 0;
- if(G->gotopos != INT_MAX){ // absolute pointing
- pos = G->gotopos;
- steps = pos - curpos;
- }else if(G->addsteps != INT_MAX){ // relative pointing
- steps = G->addsteps;
- pos = curpos + steps;
- }else break;
- if(!steps){
- info(_("Already at position"));
- break;
- }
- if(pos > maxpos || pos < 0){
- // 0...%ld
- WARNX(_("Position should be in 0...%ld"), maxpos);
- break;
- }
- if(pos == 0){
- //
- info(_("Moving to home position"));
- if(G->async) TRYFUNC(FLIHomeDevice, dev);
- else TRYFUNC(FLIHomeFocuser, dev);
- }else{
- // %ld
- info(_("Moving for %ld steps"), steps);
- if(G->async) TRYFUNC(FLIStepMotorAsync, dev, steps);
- else TRYFUNC(FLIStepMotor, dev, steps);
- }
- }while(0);
- TRYFUNC(FLIGetStepperPosition, dev, &focuserpos);
- if(!fli_err){
- green("FOCPOS=%ld\n", focuserpos);
- curpos = focuserpos;
- }else DBG("Error getting fpos: %ld", fli_err);
- TRYFUNC(FLIClose, dev);
- }
- if(!nfocs) WARNX(_("No focusers found"));
- for (i = 0; i < num; i++)
- FREE(cam[i].name);
- FREE(cam);
- /*
- * Find wheels and work with each of them
- */
- num = findcams(FLIDOMAIN_USB | FLIDEVICE_FILTERWHEEL, &cam);
- int nwheels = 0;
- for (i = 0; i < num; i++){
- TRYFUNC(FLIOpen, &dev, cam[i].name, cam[i].domain);
- if(fli_err) continue;
- TRYFUNC(FLIGetFilterCount, dev, <mp);
- if(fli_err || ltmp < 2){// not a wheel
- TRYFUNC(FLIClose, dev);
- continue;
- }
- info(_("Wheel '%s', domain %s"), cam[i].name, cam[i].dname);
- green("WHEELTOTALPOS=%ld\n", ltmp);
- int wheelmaxpos = (int)ltmp - 1;
- TRYFUNC(FLIGetModel, dev, buff, BUFF_SIZ);
- // :\t\t%s
- if(!fli_err) info(_("Model:\t\t%s"), buff);
- TRYFUNC(FLIGetHWRevision, dev, <mp);
- // . : %ld
- if(!fli_err) info(_("HW revision: %ld"), ltmp);
- TRYFUNC(FLIGetFWRevision, dev, <mp);
- // . : %ld
- if(!fli_err) info(_("SW revision: %ld"), ltmp);
- else goto closewheeldev;
- if(G->setwheel > -1 && G->setwheel >= ltmp){
- G->setwheel = -1;
- WARNX(_("Wheel position should be from 0 to %ld"), ltmp - 1);
- }
- /**
- TRYFUNC(FLIHomeDevice, dev);
- int ii;
- for(ii = 0; ii < 100; ++ii){
- TRYFUNC(FLIGetStepperPosition, dev, <mp);
- if(!fli_err) printf("%ld\t", ltmp);
- TRYFUNC( FLIGetStepsRemaining, dev, <mp);
- if(!fli_err) printf("%ld\t", ltmp);
- TRYFUNC(FLIGetFilterPos, dev, <mp);
- if(!fli_err) printf("%ld\n", ltmp);
- usleep(50000);
- }
-
- TRYFUNC(FLIGetActiveWheel, dev, <mp);
- if(!fli_err) info(_("Wheel number: %ld"), ltmp);
- TRYFUNC(FLIGetStepperPosition, dev, <mp);
- if(!fli_err) info(_("stepper position: %ld"), ltmp);
- */
- ++nwheels;
- if(G->setwheel > -1){
- ltmp = G->setwheel;
- if(ltmp > wheelmaxpos){
- WARNX(_("Position is too big (max %d)"), wheelmaxpos);
- goto closewheeldev;
- }
- TRYFUNC(FLISetFilterPos, dev, ltmp);
- if(!fli_err) info(_("Arrive to position"));
- }
- // this function returns -1 every connection without SETpos!!!
- TRYFUNC(FLIGetFilterPos, dev, &filterpos);
- if(!fli_err && filterpos > -1){
- green("WHEELPOS=%ld\n", filterpos);
- }else{
- filterpos = -1;
- // so try to check current position by steps
- TRYFUNC(FLIGetStepperPosition, dev, <mp);
- if(ltmp < 0) ltmp = -ltmp;
- DBG("steps: %ld", ltmp);
- if(!fli_err){
- int pos = (ltmp - WHEEL_POS0STPS+WHEEL_STEPPOS/2)/WHEEL_STEPPOS;
- DBG("pos = %d", pos);
- if(pos > -1 && pos <= wheelmaxpos){
- filterpos = pos;
- green("WHEELPOS=%ld\n", filterpos);
- }
- }
- }
-closewheeldev:
- TRYFUNC(FLIClose, dev);
- }
- if(!nwheels) WARNX(_("No wheels found"));
- for (i = 0; i < num; i++)
- FREE(cam[i].name);
- FREE(cam);
- /*
- * Find CCDs and work with each of them
- */
- num = findcams(FLIDOMAIN_USB | FLIDEVICE_CAMERA, &cam);
- if(!num) WARNX(_("No CCD found"));
- for (i = 0; i < num; i++){
- long x0,x1, y0,y1, row, img_rows, row_width;
- u_int16_t *img;
- int j;
- // '%s' %s
- info(_("Camera '%s', domain %s"), cam[i].name, cam[i].dname);
- TRYFUNC(FLIOpen, &dev, cam[i].name, cam[i].domain);
- if(fli_err) continue;
- TRYFUNC(FLIGetModel, dev, buff, BUFF_SIZ);
- // :\t\t%s
- if(!fli_err) info(_("Model:\t\t%s"), buff);
- camera = strdup(buff);
- TRYFUNC(FLIGetHWRevision, dev, <mp);
- // . : %ld
- if(!fli_err) info(_("HW revision: %ld"), ltmp);
- TRYFUNC(FLIGetFWRevision, dev, <mp);
- // . : %ld
- if(!fli_err) info(_("SW revision: %ld"), ltmp);
- TRYFUNC(FLIGetPixelSize, dev, &pixX, &pixY);
- // : %g x %g
- if(!fli_err) info(_("Pixel size: %g x %g"), pixX, pixY);
- TRYFUNC(FLIGetVisibleArea, dev, &x0, &y0, &x1, &y1);
- snprintf(viewfield, 80, "(%ld, %ld)(%ld, %ld)", x0, y0, x1, y1);
- // : %s
- if(!fli_err) info(_("Field of view: %s"), viewfield);
- if(G->X1 > x1) G->X1 = x1;
- if(G->Y1 > y1) G->Y1 = y1;
- TRYFUNC(FLIGetArrayArea, dev, &x0, &y0, &x1, &y1);
- // : (%ld, %ld)(%ld, %ld)
- if(!fli_err) info(_("Array field: (%ld, %ld)(%ld, %ld)"), x0, y0, x1, y1);
- TRYFUNC(FLISetHBin, dev, G->hbin);
- TRYFUNC(FLISetVBin, dev, G->vbin);
- if(G->X0 == -1) G->X0 = x0; // default values
- if(G->Y0 == -1) G->Y0 = y0;
- if(G->X1 == -1) G->X1 = x1;
- if(G->Y1 == -1) G->Y1 = y1;
- row_width = (G->X1 - G->X0) / G->hbin;
- img_rows = (G->Y1 - G->Y0) / G->vbin;
- TRYFUNC(FLISetImageArea, dev, G->X0, G->Y0,
- G->X0 + (G->X1 - G->X0) / G->hbin, G->Y0 + (G->Y1 - G->Y0) / G->vbin);
- TRYFUNC(FLISetNFlushes, dev, G->nflushes);
- if(G->temperature < 40.){
- // " : %g \n"
- green(_("Set CCD temperature to %g degr.C\n"), G->temperature);
- TRYFUNC(FLISetTemperature, dev, G->temperature);
- }
- TRYFUNC(FLIGetTemperature, dev, &t_int);
- if(!fli_err) green("CCDTEMP=%.1f\n", t_int);
- TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext);
- if(!fli_err) green("EXTTEMP=%.1f\n", t_ext);
- if(G->shtr_cmd > -1){
- flishutter_t shtr = G->shtr_cmd;
- char *str = NULL;
- switch(shtr){
- case FLI_SHUTTER_CLOSE:
- str = "close";
- break;
- case FLI_SHUTTER_OPEN:
- str = "open";
- break;
- case FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_LOW:
- str = "open @ LOW";
- break;
- case FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL|FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH:
- str = "open @ HIGH";
- break;
- default:
- str = "WTF?";
- }
- green(_("%s CCD shutter\n"), str);
- TRYFUNC(FLIControlShutter, dev, shtr);
- /*for(int i = 0; i < 100; ++i){
- long iop;
- TRYFUNC(FLIReadIOPort, dev, &iop);
- if(!r) printf("I/O port data: 0x%02lx\n", iop);
- sleep(1);
- }*/
- }
- if(G->confio > -1){
- // " I/O %d\n"
- green(_("Try to convfigure I/O port as %d\n"), G->confio);
- TRYFUNC(FLIConfigureIOPort, dev, G->confio);
- }
- if(G->getio){
- long iop;
- TRYFUNC(FLIReadIOPort, dev, &iop);
- if(!fli_err) green("CCDIOPORT=0x%02lx\n", iop);
- }
- if(G->setio > -1){
- // " %d I/O\n"
- green(_("Try to write %d to I/O port\n"), G->setio);
- TRYFUNC(FLIWriteIOPort, dev, G->setio);
- }
-
- if(G->exptime < DBL_EPSILON) continue;
- /*
- char str[256];
- flimode_t m = 0;
- int ret;
- while((ret = FLIGetCameraModeString (dev, m, str, 255)) == 0){
- str[255] = 0;
- red("String %ld: %s", m, str);
- m++;
- }*/
-// TRYFUNC(FLIGetCameraModeString, dev, m, str, 255);
-
- TRYFUNC(FLISetExposureTime, dev, G->exptime);
- if(G->dark) frametype = FLI_FRAME_TYPE_DARK;
- TRYFUNC(FLISetFrameType, dev, frametype);
- if(G->_8bit){
- TRYFUNC(FLISetBitDepth, dev, FLI_MODE_8BIT);
- if(fli_err == 0) green(_("8 bit mode\n"));
- }
- TRYFUNC(FLISetCameraMode, dev, G->fast ? 0 : 1);
- if(G->fast) green(_("Fast readout mode\n"));
- if(!G->outfile) red(_("Only show statistics\n"));
- img = MALLOC(uint16_t, img_rows * row_width);
- for (j = 0; j < G->nframes; j ++){
- TRYFUNC(FLIGetTemperature, dev, &G->temperature); // temperature @ exp. start
- printf("\n\n");
- // %d\n
- printf(_("Capture frame %d\n"), j);
- TRYFUNC(FLIExposeFrame, dev);
- expStartsAt = time(NULL); //
- do{
- TRYFUNC(FLIGetTemperature, dev, &t_int);
- TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext);
- if(curtime(tm_buf)){
- // /
- info("%s: %s\tText=%.2f\tTint=%.2f\n", _("date/time"), tm_buf, t_ext, t_int);
- }
- else WARNX("curtime() error");
- TRYFUNC(FLIGetExposureStatus, dev, <mp);
- if(fli_err) continue;
- if(G->shtr_cmd > 0 && G->shtr_cmd & FLI_SHUTTER_EXTERNAL_EXPOSURE_CONTROL && ltmp == G->exptime){
- // " "
- printf(_("wait for external trigger...\n"));
- sleep(1);
- }else{
- // %.3f \n
- printf(_("%.3f seconds till exposition ends\n"), ((float)ltmp) / 1000.);
- if(ltmp > 10000) sleep(10);
- else usleep(ltmp * 1000);
- }
- }while(ltmp);
- // :
- printf(_("Read image: "));
- int portion = 0;
- for (row = 0; row < img_rows; row++){
- TRYFUNC(FLIGrabRow, dev, &img[row * row_width], row_width);
- if(fli_err) break;
- int progress = (int)(((float)row / (float)img_rows) * 100.);
- if(progress/5 > portion){
- if((++portion)%2) printf("..");
- else printf("%d%%", portion*5);
- fflush(stdout);
- }
- }
- printf("100%%\n");
- curtime(tm_buf);
- print_stat(img, row_width * img_rows);
- inline void WRITEIMG(int (*writefn)(char*,int,int,void*), char *ext){
- if(G->outfile == NULL) return;
- if(!check_filename(buff, G->outfile, ext) && !rewrite_ifexists)
- //
- WARNX(_("Can't save file"));
- else{
- if(rewrite_ifexists){
- char *p = "";
- if(strcmp(ext, "fit") == 0) p = "!";
- snprintf(buff, BUFF_SIZ, "%s%s.%s", p, G->outfile, ext);
- }
- TRYFUNC(writefn, buff, row_width, img_rows, img);
- // '%s'
- if (fli_err == 0) info(_("File saved as '%s'"), buff);
- }
- }
- #ifdef USERAW
- WRITEIMG(writeraw, "raw");
- #endif // USERAW
- WRITEIMG(writefits, "fit");
- #ifdef USEPNG
- WRITEIMG(writepng, "png");
- #endif /* USEPNG */
- if(G->pause_len){
- double delta, time1 = dtime() + G->pause_len;
- while((delta = time1 - dtime()) > 0.){
- // %d \n
- printf(_("%d seconds till pause ends\n"), (int)delta);
- TRYFUNC(FLIGetTemperature, dev, &t_int);
- TRYFUNC(FLIReadTemperature, dev, FLI_TEMPERATURE_EXTERNAL, &t_ext);
- if(curtime(tm_buf)){
- // /
- info("%s: %s\tText=%.2f\tTint=%.2f\n", _("date/time"), tm_buf, t_ext, t_int);
- }
- else info("curtime() error");
- if(delta > 10) sleep(10);
- else sleep((int)delta);
- }
- }
- }
- FREE(camera);
- FREE(img);
- TRYFUNC(FLIClose, dev);
- }
- for (i = 0; i < num; i++)
- FREE(cam[i].name);
- FREE(cam);
+ parse_args(argc, argv);
+ if(fli_init()) return 1;
+ focusers();
+ wheels();
+ ccds();
return 0;
}
-static int findcams(flidomain_t domain, cam_t **cam){
- char **tmplist;
- int numcams = 0;
- TRYFUNC(FLIList, domain, &tmplist);
- if (tmplist && tmplist[0]){
- int i, cams = 0;
- for (i = 0; tmplist[i]; i++) cams++;
- if ((*cam = realloc(*cam, (numcams + cams) * sizeof(cam_t))) == NULL)
- ERR("realloc() failed");
- for (i = 0; tmplist[i]; i++){
- int j;
- cam_t *tmpcam = *cam + i;
- for (j = 0; tmplist[i][j] != '\0'; j++)
- if (tmplist[i][j] == ';'){
- tmplist[i][j] = '\0';
- break;
- }
- tmpcam->domain = domain;
- tmpcam->name = strdup(tmplist[i]);
- switch (domain & 0xff){
- case FLIDOMAIN_PARALLEL_PORT:
- tmpcam->dname = "parallel port";
- break;
- case FLIDOMAIN_USB:
- tmpcam->dname = "USB";
- ;
- break;
- case FLIDOMAIN_SERIAL:
- tmpcam->dname = "serial";
- break;
- case FLIDOMAIN_INET:
- tmpcam->dname = "inet";
- break;
- default:
- tmpcam->dname = "Unknown domain";
- break;
- }
- DBG("found: %s @ %s", tmpcam->name, tmpcam->dname);
- }
- numcams += cams;
- }
- else DBG("No devices");
- TRYFUNC(FLIFreeList, tmplist);
- return numcams;
-}
-
-#ifdef USERAW
-static int writeraw(char *filename, int width, int height, void *data){
- int fd, size, err;
- if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) == -1){
- WARN("open(%s) failed", filename);
- return -errno;
- }
- size = width * height * sizeof(u_int16_t);
- if ((err = write(fd, data, size)) != size){
- WARN("write() failed");
- err = -errno;
- }
- else err = 0;
- close(fd);
- return err;
-}
-#endif // USERAW
-
-/**
- * @brief addrec - add FITS records from file
- * @param f (i) - FITS filename
- * @param filename (i) - name of file
- */
-static void addrec(fitsfile *f, char *filename){
- FILE *fp = fopen(filename, "r");
- if(!fp) return;
- char buf[2*FLEN_CARD];
- while(fgets(buf, 2*FLEN_CARD, fp)){
- DBG("check record _%s_", buf);
- int keytype, status = 0;
- char newcard[FLEN_CARD], keyname[FLEN_CARD];
- fits_parse_template(buf, newcard, &keytype, &status);
- if(status){
- fits_report_error(stderr, status);
- continue;
- }
- DBG("reformatted to _%s_", newcard);
- strncpy(keyname, newcard, FLEN_CARD);
- char *eq = strchr(keyname, '='); if(eq) *eq = 0;
- eq = strchr(keyname, ' '); if(eq) *eq = 0;
- DBG("keyname: %s", keyname);
- fits_update_card(f, keyname, newcard, &status);
- }
-}
-
-static int writefits(char *filename, int width, int height, void *data){
- long naxes[2] = {width, height}, startTime;
- double tmp = 0.0;
- struct tm *tm_starttime;
- char buf[FLEN_CARD];
- time_t savetime = time(NULL);
- fitsfile *fp;
- TRYFITS(fits_create_file, &fp, filename);
- TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes);
- // FILE / Input file original name
- WRITEKEY(fp, TSTRING, "FILE", filename, "Input file original name");
- // ORIGIN / organization responsible for the data
- WRITEKEY(fp, TSTRING, "ORIGIN", "SAO RAS", "organization responsible for the data");
- // OBSERVAT / Observatory name
- WRITEKEY(fp, TSTRING, "OBSERVAT", "Special Astrophysical Observatory, Russia", "Observatory name");
- // DETECTOR / detector
- if(camera){
- WRITEKEY(fp, TSTRING, "DETECTOR", camera, "Detector model");
- }
- // INSTRUME / Instrument
- if(G->instrument){
- WRITEKEY(fp, TSTRING, "INSTRUME", G->instrument, "Instrument");
- }else
- WRITEKEY(fp, TSTRING, "INSTRUME", "direct imaging", "Instrument");
- snprintf(buf, 80, "%.g x %.g", pixX, pixY);
- // PXSIZE / pixel size
- WRITEKEY(fp, TSTRING, "PXSIZE", buf, "Pixel size in m");
- WRITEKEY(fp, TSTRING, "VIEWFLD", viewfield, "Camera field of view");
- // CRVAL1, CRVAL2 / Offset in X, Y
- if(G->X0) WRITEKEY(fp, TINT, "X0", &G->X0, "Subframe left border");
- if(G->Y0) WRITEKEY(fp, TINT, "Y0", &G->Y0, "Subframe upper border");
- if(G->exptime < 2.*DBL_EPSILON) sprintf(buf, "bias");
- else if(frametype == FLI_FRAME_TYPE_DARK) sprintf(buf, "dark");
- else if(G->objtype) strncpy(buf, G->objtype, FLEN_CARD-1);
- else sprintf(buf, "object");
- // IMAGETYP / object, flat, dark, bias, scan, eta, neon, push
- WRITEKEY(fp, TSTRING, "IMAGETYP", buf, "Image type");
- // DATAMAX, DATAMIN / Max,min pixel value
- int itmp = 0;
- WRITEKEY(fp, TINT, "DATAMIN", &itmp, "Min pixel value");
- //itmp = G->fast ? 255 : 65535;
- itmp = 65535;
- WRITEKEY(fp, TINT, "DATAMAX", &itmp, "Max pixel value");
- WRITEKEY(fp, TUSHORT, "STATMAX", &max, "Max data value");
- WRITEKEY(fp, TUSHORT, "STATMIN", &min, "Min data value");
- WRITEKEY(fp, TDOUBLE, "STATAVR", &avr, "Average data value");
- WRITEKEY(fp, TDOUBLE, "STATSTD", &std, "Std. of data value");
- WRITEKEY(fp, TDOUBLE, "TEMP0", &G->temperature, "Camera temperature at exp. start (degr C)");
- WRITEKEY(fp, TDOUBLE, "TEMP1", &t_int, "Camera temperature at exp. end (degr C)");
- WRITEKEY(fp, TDOUBLE, "TEMPBODY", &t_ext, "Camera body temperature at exp. end (degr C)");
- tmp = (G->temperature + t_int) / 2. + 273.15;
- // CAMTEMP / Camera temperature (K)
- WRITEKEY(fp, TDOUBLE, "CAMTEMP", &tmp, "Camera temperature (K)");
- // WHEEL & FOCUSER positions:
- tmp = (double)focuserpos / FOCSCALE;
- WRITEKEY(fp, TDOUBLE, "FOCUS", &tmp, "Current focuser position, mm");
- if(filterpos > -1)
- WRITEKEY(fp, TINT, "FILTER", &filterpos, "Current filter number");
- // EXPTIME / actual exposition time (sec)
- tmp = (double)G->exptime / 1000.;
- WRITEKEY(fp, TDOUBLE, "EXPTIME", &tmp, "Actual exposition time (sec)");
- // DATE / Creation date (YYYY-MM-DDThh:mm:ss, UTC)
- strftime(buf, 80, "%Y-%m-%dT%H:%M:%S", gmtime(&savetime));
- WRITEKEY(fp, TSTRING, "DATE", buf, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)");
- startTime = (long)expStartsAt;
- tm_starttime = localtime(&expStartsAt);
- strftime(buf, 80, "Exposition start time (UNIX)", tm_starttime);
- WRITEKEY(fp, TLONG, "UNIXTIME", &startTime, buf);
- strftime(buf, 80, "%Y/%m/%d", tm_starttime);
- // DATE-OBS / DATE (YYYY/MM/DD) OF OBS.
- WRITEKEY(fp, TSTRING, "DATE-OBS", buf, "DATE OF OBS. (YYYY/MM/DD, local)");
- strftime(buf, 80, "%H:%M:%S", tm_starttime);
- // START / Measurement start time (local) (hh:mm:ss)
- WRITEKEY(fp, TSTRING, "START", buf, "Measurement start time (hh:mm:ss, local)");
- // OBJECT / Object name
- if(G->objname){
- WRITEKEY(fp, TSTRING, "OBJECT", G->objname, "Object name");
- }
- // BINNING / Binning
- if(G->hbin != 1 || G->vbin != 1){
- snprintf(buf, 80, "%d x %d", G->hbin, G->vbin);
- WRITEKEY(fp, TSTRING, "BINNING", buf, "Binning (hbin x vbin)");
- }
- // OBSERVER / Observers
- if(G->observers){
- WRITEKEY(fp, TSTRING, "OBSERVER", G->observers, "Observers");
- }
- // PROG-ID / Observation program identifier
- if(G->prog_id){
- WRITEKEY(fp, TSTRING, "PROG-ID", G->prog_id, "Observation program identifier");
- }
- // AUTHOR / Author of the program
- if(G->author){
- WRITEKEY(fp, TSTRING, "AUTHOR", G->author, "Author of the program");
- }
- if(G->addhdr){ // add records from files
- char **nxtfile = G->addhdr;
- while(*nxtfile){
- addrec(fp, *nxtfile++);
- }
- }
- TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, data);
- TRYFITS(fits_close_file, fp);
- return 0;
-}
-
-#ifdef USEPNG
-static int writepng(char *filename, int width, int height, void *data){
- int err;
- FILE *fp = NULL;
- png_structp pngptr = NULL;
- png_infop infoptr = NULL;
- void *row;
- if ((fp = fopen(filename, "wb")) == NULL){
- err = -errno;
- goto done;
- }
- if ((pngptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
- NULL, NULL, NULL)) == NULL){
- err = -ENOMEM;
- goto done;
- }
- if ((infoptr = png_create_info_struct(pngptr)) == NULL){
- err = -ENOMEM;
- goto done;
- }
- png_init_io(pngptr, fp);
- png_set_compression_level(pngptr, Z_BEST_COMPRESSION);
- png_set_IHDR(pngptr, infoptr, width, height, 16, PNG_COLOR_TYPE_GRAY,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
- png_write_info(pngptr, infoptr);
- png_set_swap(pngptr);
- for(row = data; height > 0; row += width * sizeof(u_int16_t), height--)
- png_write_row(pngptr, row);
- png_write_end(pngptr, infoptr);
- err = 0;
- done:
- if(fp) fclose(fp);
- if(pngptr) png_destroy_write_struct(&pngptr, &infoptr);
- return err;
-}
-#endif /* USEPNG */
-
-static void print_stat(u_int16_t *img, long size){
- long i, Noverld = 0L;
- double pv, sum=0., sum2=0., sz = (double)size;
- u_int16_t *ptr = img, val;
- max = 0; min = 65535;
- for(i = 0; i < size; i++, ptr++){
- val = *ptr;
- pv = (double) val;
- sum += pv;
- sum2 += (pv * pv);
- if(max < val) max = val;
- if(min > val) min = val;
- if(val >= 65530) Noverld++;
- }
- // :\n
- printf(_("Image stat:\n"));
- avr = sum/sz;
- printf("avr = %.1f, std = %.1f, Noverload = %ld\n", avr,
- std = sqrt(fabs(sum2/sz - avr*avr)), Noverld);
- printf("max = %u, min = %u, size = %ld\n", max, min, size);
-}
diff --git a/fli_control/main.h b/fli_control/main.h
deleted file mode 100644
index a6e263b..0000000
--- a/fli_control/main.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * geany_encoding=koi8-r
- * main.h
- *
- * Copyright 2017 Edward V. Emelianov
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- */
-#pragma once
-#ifndef __MAIN_H__
-#define __MAIN_H__
-
-#include "usefull_macros.h"
-#include "cmdlnopts.h"
-
-#ifdef USEPNG
-#include
-static int writepng(char *filename, int width, int height, void *data);
-#endif /* USEPNG */
-
-#include
-
-#define LIBVERSIZ 1024
-
-// wheel position in steps = WHEEL_POS0STPS + WHEEL_STEPPOS*N
-#define WHEEL_POS0STPS (239)
-#define WHEEL_STEPPOS (48)
-// 1mm == FOCSCALE steps of focuser
-#define FOCSCALE (10000.)
-
-typedef struct{
- flidomain_t domain;
- char *dname;
- char *name;
-}cam_t;
-
-static int findcams(flidomain_t domain, cam_t **cam);
-
-#ifdef USERAW
-static int writeraw(char *filename, int width, int height, void *data);
-#endif // USERAW
-
-#define TRYFITS(f, ...) \
-do{ int status = 0; \
- f(__VA_ARGS__, &status); \
- if (status){ \
- fits_report_error(stderr, status); \
- return -1;} \
-}while(0)
-#define WRITEKEY(...) \
-do{ int status = 0; \
- fits_write_key(__VA_ARGS__, &status); \
- if(status) fits_report_error(stderr, status);\
-}while(0)
-static int writefits(char *filename, int width, int height, void *data);
-
-
-#endif // __MAIN_H__
diff --git a/fli_control/parseargs.c b/fli_control/parseargs.c
deleted file mode 100644
index b235752..0000000
--- a/fli_control/parseargs.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/* geany_encoding=koi8-r
- * parseargs.c - parsing command line arguments & print help
- *
- * Copyright 2013 Edward V. Emelianoff
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include // printf
-#include // getopt_long
-#include // calloc, exit, strtoll
-#include // assert
-#include // strdup, strchr, strlen
-#include // strcasecmp
-#include // INT_MAX & so on
-#include // gettext
-#include // isalpha
-#include "parseargs.h"
-#include "usefull_macros.h"
-
-char *helpstring = "%s\n";
-
-/**
- * Change standard help header
- * MAY consist ONE "%s" for progname
- * @param str (i) - new format
- */
-void change_helpstring(char *s){
- int pcount = 0, scount = 0;
- char *str = s;
- // check `helpstring` and set it to default in case of error
- for(; pcount < 2; str += 2){
- if(!(str = strchr(str, '%'))) break;
- if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%"
- else{
- str += 2; // pass next '%'
- continue;
- }
- if(str[1] == 's') scount++; // increment "%s" counter
- };
- if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong
- /// " "
- ERRX(_("Wrong helpstring!"));
- }
- helpstring = s;
-}
-
-/**
- * Carefull atoll/atoi
- * @param num (o) - returning value (or NULL if you wish only check number) - allocated by user
- * @param str (i) - string with number must not be NULL
- * @param t (i) - T_INT for integer or T_LLONG for long long (if argtype would be wided, may add more)
- * @return TRUE if conversion sone without errors, FALSE otherwise
- */
-static bool myatoll(void *num, char *str, argtype t){
- long long tmp, *llptr;
- int *iptr;
- char *endptr;
- assert(str);
- assert(num);
- tmp = strtoll(str, &endptr, 0);
- if(endptr == str || *str == '\0' || *endptr != '\0')
- return FALSE;
- switch(t){
- case arg_longlong:
- llptr = (long long*) num;
- *llptr = tmp;
- break;
- case arg_int:
- default:
- if(tmp < INT_MIN || tmp > INT_MAX){
- /// " "
- WARNX(_("Integer out of range"));
- return FALSE;
- }
- iptr = (int*)num;
- *iptr = (int)tmp;
- }
- return TRUE;
-}
-
-// the same as myatoll but for double
-// There's no NAN & INF checking here (what if they would be needed?)
-static bool myatod(void *num, const char *str, argtype t){
- double tmp, *dptr;
- float *fptr;
- char *endptr;
- assert(str);
- tmp = strtod(str, &endptr);
- if(endptr == str || *str == '\0' || *endptr != '\0')
- return FALSE;
- switch(t){
- case arg_double:
- dptr = (double *) num;
- *dptr = tmp;
- break;
- case arg_float:
- default:
- fptr = (float *) num;
- *fptr = (float)tmp;
- break;
- }
- return TRUE;
-}
-
-/**
- * Get index of current option in array options
- * @param opt (i) - returning val of getopt_long
- * @param options (i) - array of options
- * @return index in array
- */
-static int get_optind(int opt, myoption *options){
- int oind;
- myoption *opts = options;
- assert(opts);
- for(oind = 0; opts->name && opts->val != opt; oind++, opts++);
- if(!opts->name || opts->val != opt) // no such parameter
- showhelp(-1, options);
- return oind;
-}
-
-/**
- * reallocate new value in array of multiple repeating arguments
- * @arg paptr - address of pointer to array (**void)
- * @arg type - its type (for realloc)
- * @return pointer to new (next) value
- */
-void *get_aptr(void *paptr, argtype type){
- int i = 1;
- void **aptr = *((void***)paptr);
- if(aptr){ // there's something in array
- void **p = aptr;
- while(*p++) ++i;
- }
- size_t sz = 0;
- switch(type){
- default:
- case arg_none:
- /// " !"
- ERRX("Can't use multiple args with arg_none!");
- break;
- case arg_int:
- sz = sizeof(int);
- break;
- case arg_longlong:
- sz = sizeof(long long);
- break;
- case arg_double:
- sz = sizeof(double);
- break;
- case arg_float:
- sz = sizeof(float);
- break;
- case arg_string:
- sz = 0;
- break;
- /* case arg_function:
- sz = sizeof(argfn *);
- break;*/
- }
- aptr = realloc(aptr, (i + 1) * sizeof(void*));
- *((void***)paptr) = aptr;
- aptr[i] = NULL;
- if(sz){
- aptr[i - 1] = malloc(sz);
- }else
- aptr[i - 1] = &aptr[i - 1];
- return aptr[i - 1];
-}
-
-
-/**
- * Parse command line arguments
- * ! If arg is string, then value will be strdup'ed!
- *
- * @param argc (io) - address of argc of main(), return value of argc stay after `getopt`
- * @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt`
- * BE CAREFUL! if you wanna use full argc & argv, save their original values before
- * calling this function
- * @param options (i) - array of `myoption` for arguments parcing
- *
- * @exit: in case of error this function show help & make `exit(-1)`
- */
-void parseargs(int *argc, char ***argv, myoption *options){
- char *short_options, *soptr;
- struct option *long_options, *loptr;
- size_t optsize, i;
- myoption *opts = options;
- // check whether there is at least one options
- assert(opts);
- assert(opts[0].name);
- // first we count how much values are in opts
- for(optsize = 0; opts->name; optsize++, opts++);
- // now we can allocate memory
- short_options = calloc(optsize * 3 + 1, 1); // multiply by three for '::' in case of args in opts
- long_options = calloc(optsize + 1, sizeof(struct option));
- opts = options; loptr = long_options; soptr = short_options;
- // in debug mode check the parameters are not repeated
-#ifdef EBUG
- char **longlist = MALLOC(char*, optsize);
- char *shortlist = MALLOC(char, optsize);
-#endif
- // fill short/long parameters and make a simple checking
- for(i = 0; i < optsize; i++, loptr++, opts++){
- // check
- assert(opts->name); // check name
-#ifdef EBUG
- longlist[i] = strdup(opts->name);
-#endif
- if(opts->has_arg){
- assert(opts->type != arg_none); // check error with arg type
- assert(opts->argptr); // check pointer
- }
- if(opts->type != arg_none) // if there is a flag without arg, check its pointer
- assert(opts->argptr);
- // fill long_options
- // don't do memcmp: what if there would be different alignment?
- loptr->name = opts->name;
- loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1;
- loptr->flag = opts->flag;
- loptr->val = opts->val;
- // fill short options if they are:
- if(!opts->flag && opts->val){
-#ifdef EBUG
- shortlist[i] = (char) opts->val;
-#endif
- *soptr++ = opts->val;
- if(loptr->has_arg) // add ':' if option has required argument
- *soptr++ = ':';
- if(loptr->has_arg == 2) // add '::' if option has optional argument
- *soptr++ = ':';
- }
- }
- // sort all lists & check for repeating
-#ifdef EBUG
- int cmpstringp(const void *p1, const void *p2){
- return strcmp(* (char * const *) p1, * (char * const *) p2);
- }
- int cmpcharp(const void *p1, const void *p2){
- return (int)(*(char * const)p1 - *(char *const)p2);
- }
- qsort(longlist, optsize, sizeof(char *), cmpstringp);
- qsort(shortlist,optsize, sizeof(char), cmpcharp);
- char *prevl = longlist[0], prevshrt = shortlist[0];
- for(i = 1; i < optsize; ++i){
- if(longlist[i]){
- if(prevl){
- if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl);
- }
- prevl = longlist[i];
- }
- if(shortlist[i]){
- if(prevshrt){
- if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt);
- }
- prevshrt = shortlist[i];
- }
- }
-#endif
- // now we have both long_options & short_options and can parse `getopt_long`
- while(1){
- int opt;
- int oindex = 0, optind = 0; // oindex - number of option in argv, optind - number in options[]
- if((opt = getopt_long(*argc, *argv, short_options, long_options, &oindex)) == -1) break;
- if(opt == '?'){
- opt = optopt;
- optind = get_optind(opt, options);
- if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR)
- showhelp(optind, options); // need argument
- }
- else{
- if(opt == 0 || oindex > 0) optind = oindex;
- else optind = get_optind(opt, options);
- }
- opts = &options[optind];
- // if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag
- // now check option
- if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR)
- if(!optarg) showhelp(optind, options); // need argument
- void *aptr;
- if(opts->has_arg == MULT_PAR){
- aptr = get_aptr(opts->argptr, opts->type);
- }else
- aptr = opts->argptr;
- bool result = TRUE;
- // even if there is no argument, but argptr != NULL, think that optarg = "1"
- if(!optarg) optarg = "1";
- switch(opts->type){
- default:
- case arg_none:
- if(opts->argptr) *((int*)aptr) += 1; // increment value
- break;
- case arg_int:
- result = myatoll(aptr, optarg, arg_int);
- break;
- case arg_longlong:
- result = myatoll(aptr, optarg, arg_longlong);
- break;
- case arg_double:
- result = myatod(aptr, optarg, arg_double);
- break;
- case arg_float:
- result = myatod(aptr, optarg, arg_float);
- break;
- case arg_string:
- result = (*((void**)aptr) = (void*)strdup(optarg));
- break;
- case arg_function:
- result = ((argfn)aptr)(optarg);
- break;
- }
- if(!result){
- showhelp(optind, options);
- }
- }
- *argc -= optind;
- *argv += optind;
-}
-
-/**
- * compare function for qsort
- * first - sort by short options; second - sort arguments without sort opts (by long options)
- */
-static int argsort(const void *a1, const void *a2){
- const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2;
- const char *l1 = o1->name, *l2 = o2->name;
- int s1 = o1->val, s2 = o2->val;
- int *f1 = o1->flag, *f2 = o2->flag;
- // check if both options has short arg
- if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg
- return (s1 - s2);
- }else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long
- return strcmp(l1, l2);
- }else{ // only one have short arg -- return it
- if(f2 || !s2) return -1; // a1 have short - it is 'lesser'
- else return 1;
- }
-}
-
-/**
- * Show help information based on myoption->help values
- * @param oindex (i) - if non-negative, show only help by myoption[oindex].help
- * @param options (i) - array of `myoption`
- *
- * @exit: run `exit(-1)` !!!
- */
-void showhelp(int oindex, myoption *options){
- int max_opt_len = 0; // max len of options substring - for right indentation
- const int bufsz = 255;
- char buf[bufsz+1];
- myoption *opts = options;
- assert(opts);
- assert(opts[0].name); // check whether there is at least one options
- if(oindex > -1){ // print only one message
- opts = &options[oindex];
- printf(" ");
- if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val);
- printf("--%s", opts->name);
- if(opts->has_arg == 1) printf("=arg");
- else if(opts->has_arg == 2) printf("[=arg]");
- printf(" %s\n", _(opts->help));
- exit(-1);
- }
- // header, by default is just "progname\n"
- printf("\n");
- if(strstr(helpstring, "%s")) // print progname
- printf(helpstring, __progname);
- else // only text
- printf("%s", helpstring);
- printf("\n");
- // count max_opt_len
- do{
- int L = strlen(opts->name);
- if(max_opt_len < L) max_opt_len = L;
- }while((++opts)->name);
- max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols
- opts = options;
- // count amount of options
- int N; for(N = 0; opts->name; ++N, ++opts);
- if(N == 0) exit(-2);
- // Now print all help (sorted)
- opts = options;
- qsort(opts, N, sizeof(myoption), argsort);
- do{
- int p = sprintf(buf, " "); // a little indent
- if(!opts->flag && opts->val) // .val is short argument
- p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val);
- p += snprintf(buf+p, bufsz-p, "--%s", opts->name);
- if(opts->has_arg == 1) // required argument
- p += snprintf(buf+p, bufsz-p, "=arg");
- else if(opts->has_arg == 2) // optional argument
- p += snprintf(buf+p, bufsz-p, "[=arg]");
- assert(p < max_opt_len); // there would be magic if p >= max_opt_len
- printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after
- ++opts;
- }while(--N);
- printf("\n\n");
- exit(-1);
-}
-
-/**
- * get suboptions from parameter string
- * @param str - parameter string
- * @param opt - pointer to suboptions structure
- * @return TRUE if all OK
- */
-bool get_suboption(char *str, mysuboption *opt){
- int findsubopt(char *par, mysuboption *so){
- int idx = 0;
- if(!par) return -1;
- while(so[idx].name){
- if(strcasecmp(par, so[idx].name) == 0) return idx;
- ++idx;
- }
- return -1; // badarg
- }
- bool opt_setarg(mysuboption *so, int idx, char *val){
- mysuboption *soptr = &so[idx];
- bool result = FALSE;
- void *aptr = soptr->argptr;
- switch(soptr->type){
- default:
- case arg_none:
- if(soptr->argptr) *((int*)aptr) += 1; // increment value
- result = TRUE;
- break;
- case arg_int:
- result = myatoll(aptr, val, arg_int);
- break;
- case arg_longlong:
- result = myatoll(aptr, val, arg_longlong);
- break;
- case arg_double:
- result = myatod(aptr, val, arg_double);
- break;
- case arg_float:
- result = myatod(aptr, val, arg_float);
- break;
- case arg_string:
- result = (*((void**)aptr) = (void*)strdup(val));
- break;
- case arg_function:
- result = ((argfn)aptr)(val);
- break;
- }
- return result;
- }
- char *tok;
- bool ret = FALSE;
- char *tmpbuf;
- tok = strtok_r(str, ":,", &tmpbuf);
- do{
- char *val = strchr(tok, '=');
- int noarg = 0;
- if(val == NULL){ // no args
- val = "1";
- noarg = 1;
- }else{
- *val++ = '\0';
- if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after =
- val = "1"; noarg = 1;
- }
- }
- int idx = findsubopt(tok, opt);
- if(idx < 0){
- /// " : %s"
- WARNX(_("Wrong parameter: %s"), tok);
- goto returning;
- }
- if(noarg && opt[idx].has_arg == NEED_ARG){
- /// "%s: !"
- WARNX(_("%s: argument needed!"), tok);
- goto returning;
- }
- if(!opt_setarg(opt, idx, val)){
- /// " \"%s\" \"%s\""
- WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok);
- goto returning;
- }
- }while((tok = strtok_r(NULL, ":,", &tmpbuf)));
- ret = TRUE;
-returning:
- return ret;
-}
diff --git a/fli_control/parseargs.h b/fli_control/parseargs.h
deleted file mode 100644
index a0ac099..0000000
--- a/fli_control/parseargs.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * parseargs.h - headers for parsing command line arguments
- *
- * Copyright 2013 Edward V. Emelianoff
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#pragma once
-#ifndef __PARSEARGS_H__
-#define __PARSEARGS_H__
-
-#include // bool
-#include
-
-#ifndef TRUE
- #define TRUE true
-#endif
-
-#ifndef FALSE
- #define FALSE false
-#endif
-
-// macro for argptr
-#define APTR(x) ((void*)x)
-
-// if argptr is a function:
-typedef bool(*argfn)(void *arg);
-
-/*
- * type of getopt's argument
- * WARNING!
- * My function change value of flags by pointer, so if you want to use another type
- * make a latter conversion, example:
- * char charg;
- * int iarg;
- * myoption opts[] = {
- * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option};
- * ..(parse args)..
- * charg = (char) iarg;
- */
-typedef enum {
- arg_none = 0, // no arg
- arg_int, // integer
- arg_longlong, // long long
- arg_double, // double
- arg_float, // float
- arg_string, // char *
- arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)`
-} argtype;
-
-/*
- * Structure for getopt_long & help
- * BE CAREFUL: .argptr is pointer to data or pointer to function,
- * conversion depends on .type
- *
- * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext,
- * but you can redefine it before `#include "parseargs.h"`
- *
- * if arg is string, then value wil be strdup'ed like that:
- * char *str;
- * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option};
- * *(opts[1].str) = strdup(optarg);
- * in other cases argptr should be address of some variable (or pointer to allocated memory)
- *
- * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr
- *
- * !!!LAST VALUE OF ARRAY SHOULD BE `end_option` or ZEROS !!!
- *
- */
-typedef enum{
- NO_ARGS = 0, // first three are the same as in getopt_long
- NEED_ARG = 1,
- OPT_ARG = 2,
- MULT_PAR
-} hasarg;
-
-typedef struct{
- // these are from struct option:
- const char *name; // long option's name
- hasarg has_arg; // 0 - no args, 1 - nesessary arg, 2 - optionally arg, 4 - need arg & key can repeat (args are stored in null-terminated array)
- int *flag; // NULL to return val, pointer to int - to set its value of val (function returns 0)
- int val; // short opt name (if flag == NULL) or flag's value
- // and these are mine:
- argtype type; // type of argument
- void *argptr; // pointer to variable to assign optarg value or function `bool (*fn)(char *optarg, int N)`
- const char *help; // help string which would be shown in function `showhelp` or NULL
-} myoption;
-
-/*
- * Suboptions structure, almost the same like myoption
- * used in parse_subopts()
- */
-typedef struct{
- const char *name;
- hasarg has_arg;
- argtype type;
- void *argptr;
-} mysuboption;
-
-// last string of array (all zeros)
-#define end_option {0,0,0,0,0,0,0}
-#define end_suboption {0,0,0,0}
-
-extern const char *__progname;
-
-void showhelp(int oindex, myoption *options);
-void parseargs(int *argc, char ***argv, myoption *options);
-void change_helpstring(char *s);
-bool get_suboption(char *str, mysuboption *opt);
-
-#endif // __PARSEARGS_H__
diff --git a/fli_control/usefull_macros.c b/fli_control/usefull_macros.c
deleted file mode 100644
index 9975de2..0000000
--- a/fli_control/usefull_macros.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * usefull_macros.h - a set of usefull functions: memory, color etc
- *
- * Copyright 2013 Edward V. Emelianoff
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include "usefull_macros.h"
-
-/**
- * function for different purposes that need to know time intervals
- * @return double value: time in seconds
- */
-double dtime(){
- double t;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- t = tv.tv_sec + ((double)tv.tv_usec)/1e6;
- return t;
-}
-
-/******************************************************************************\
- * Coloured terminal
-\******************************************************************************/
-int globErr = 0; // errno for WARN/ERR
-
-// pointers to coloured output printf
-int (*red)(const char *fmt, ...);
-int (*green)(const char *fmt, ...);
-int (*_WARN)(const char *fmt, ...);
-
-/*
- * format red / green messages
- * name: r_pr_, g_pr_
- * @param fmt ... - printf-like format
- * @return number of printed symbols
- */
-int r_pr_(const char *fmt, ...){
- va_list ar; int i;
- printf(RED);
- va_start(ar, fmt);
- i = vprintf(fmt, ar);
- va_end(ar);
- printf(OLDCOLOR);
- return i;
-}
-int g_pr_(const char *fmt, ...){
- va_list ar; int i;
- printf(GREEN);
- va_start(ar, fmt);
- i = vprintf(fmt, ar);
- va_end(ar);
- printf(OLDCOLOR);
- return i;
-}
-/*
- * print red error/warning messages (if output is a tty)
- * @param fmt ... - printf-like format
- * @return number of printed symbols
- */
-int r_WARN(const char *fmt, ...){
- va_list ar; int i = 1;
- fprintf(stderr, RED);
- va_start(ar, fmt);
- if(globErr){
- errno = globErr;
- vwarn(fmt, ar);
- errno = 0;
- }else
- i = vfprintf(stderr, fmt, ar);
- va_end(ar);
- i++;
- fprintf(stderr, OLDCOLOR "\n");
- return i;
-}
-
-static const char stars[] = "****************************************";
-/*
- * notty variants of coloured printf
- * name: s_WARN, r_pr_notty
- * @param fmt ... - printf-like format
- * @return number of printed symbols
- */
-int s_WARN(const char *fmt, ...){
- va_list ar; int i;
- i = fprintf(stderr, "\n%s\n", stars);
- va_start(ar, fmt);
- if(globErr){
- errno = globErr;
- vwarn(fmt, ar);
- errno = 0;
- }else
- i = +vfprintf(stderr, fmt, ar);
- va_end(ar);
- i += fprintf(stderr, "\n%s\n", stars);
- i += fprintf(stderr, "\n");
- return i;
-}
-int r_pr_notty(const char *fmt, ...){
- va_list ar; int i;
- i = printf("\n%s\n", stars);
- va_start(ar, fmt);
- i += vprintf(fmt, ar);
- va_end(ar);
- i += printf("\n%s\n", stars);
- return i;
-}
-
-/**
- * Run this function in the beginning of main() to setup locale & coloured output
- */
-void initial_setup(){
- // setup coloured output
- if(isatty(STDOUT_FILENO)){ // make color output in tty
- red = r_pr_; green = g_pr_;
- }else{ // no colors in case of pipe
- red = r_pr_notty; green = printf;
- }
- if(isatty(STDERR_FILENO)) _WARN = r_WARN;
- else _WARN = s_WARN;
- // Setup locale
- setlocale(LC_ALL, "");
- setlocale(LC_NUMERIC, "C");
-#if defined GETTEXT_PACKAGE && defined LOCALEDIR
- bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
- textdomain(GETTEXT_PACKAGE);
-#endif
-}
-
-/******************************************************************************\
- * Memory
-\******************************************************************************/
-/*
- * safe memory allocation for macro ALLOC
- * @param N - number of elements to allocate
- * @param S - size of single element (typically sizeof)
- * @return pointer to allocated memory area
- */
-void *my_alloc(size_t N, size_t S){
- void *p = calloc(N, S);
- if(!p) ERR("malloc");
- //assert(p);
- return p;
-}
-
-/**
- * Mmap file to a memory area
- *
- * @param filename (i) - name of file to mmap
- * @return stuct with mmap'ed file or die
- */
-mmapbuf *My_mmap(char *filename){
- int fd;
- char *ptr;
- size_t Mlen;
- struct stat statbuf;
- /// " !"
- if(!filename){
- WARNX(_("No filename given!"));
- return NULL;
- }
- if((fd = open(filename, O_RDONLY)) < 0){
- /// " %s "
- WARN(_("Can't open %s for reading"), filename);
- return NULL;
- }
- if(fstat (fd, &statbuf) < 0){
- /// " stat %s"
- WARN(_("Can't stat %s"), filename);
- close(fd);
- return NULL;
- }
- Mlen = statbuf.st_size;
- if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){
- /// " mmap"
- WARN(_("Mmap error for input"));
- close(fd);
- return NULL;
- }
- /// " mmap' "
- if(close(fd)) WARN(_("Can't close mmap'ed file"));
- mmapbuf *ret = MALLOC(mmapbuf, 1);
- ret->data = ptr;
- ret->len = Mlen;
- return ret;
-}
-
-void My_munmap(mmapbuf *b){
- if(munmap(b->data, b->len)){
- /// " munmap"
- WARN(_("Can't munmap"));
- }
- FREE(b);
-}
-
-
-/******************************************************************************\
- * Terminal in no-echo mode
-\******************************************************************************/
-static struct termios oldt, newt; // terminal flags
-static int console_changed = 0;
-// run on exit:
-void restore_console(){
- if(console_changed)
- tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state
- console_changed = 0;
-}
-
-// initial setup:
-void setup_con(){
- if(console_changed) return;
- tcgetattr(STDIN_FILENO, &oldt);
- newt = oldt;
- newt.c_lflag &= ~(ICANON | ECHO);
- if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){
- /// " "
- WARN(_("Can't setup console"));
- tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
- signals(0); //quit?
- }
- console_changed = 1;
-}
-
-/**
- * Read character from console without echo
- * @return char readed
- */
-int read_console(){
- int rb;
- struct timeval tv;
- int retval;
- fd_set rfds;
- FD_ZERO(&rfds);
- FD_SET(STDIN_FILENO, &rfds);
- tv.tv_sec = 0; tv.tv_usec = 10000;
- retval = select(1, &rfds, NULL, NULL, &tv);
- if(!retval) rb = 0;
- else {
- if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar();
- else rb = 0;
- }
- return rb;
-}
-
-/**
- * getchar() without echo
- * wait until at least one character pressed
- * @return character readed
- */
-int mygetchar(){ // getchar() without need of pressing ENTER
- int ret;
- do ret = read_console();
- while(ret == 0);
- return ret;
-}
-
-
-/******************************************************************************\
- * TTY with select()
-\******************************************************************************/
-static struct termio oldtty, tty; // TTY flags
-static int comfd = -1; // TTY fd
-
-// run on exit:
-void restore_tty(){
- if(comfd == -1) return;
- ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state
- close(comfd);
- comfd = -1;
-}
-
-#ifndef BAUD_RATE
-#define BAUD_RATE B9600
-#endif
-// init:
-void tty_init(char *comdev){
- DBG("\nOpen port...\n");
- if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
- WARN("Can't use port %s\n",comdev);
- ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state
- close(comfd);
- signals(0); // quit?
- }
- DBG(" OK\nGet current settings... ");
- if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings
- /// " "
- WARN(_("Can't get settings"));
- signals(0);
- }
- tty = oldtty;
- tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG)
- tty.c_oflag = 0;
- tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl
- tty.c_cc[VMIN] = 0; // non-canonical mode
- tty.c_cc[VTIME] = 5;
- if(ioctl(comfd,TCSETA,&tty) < 0){
- /// " "
- WARN(_("Can't set settings"));
- signals(0);
- }
- DBG(" OK\n");
-}
-/**
- * Read data from TTY
- * @param buff (o) - buffer for data read
- * @param length - buffer len
- * @return amount of readed bytes
- */
-size_t read_tty(uint8_t *buff, size_t length){
- ssize_t L = 0;
- fd_set rfds;
- struct timeval tv;
- int retval;
- FD_ZERO(&rfds);
- FD_SET(comfd, &rfds);
- tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms
- retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
- if (!retval) return 0;
- if(FD_ISSET(comfd, &rfds)){
- if((L = read(comfd, buff, length)) < 1) return 0;
- }
- return (size_t)L;
-}
-
-int write_tty(uint8_t *buff, size_t length){
- ssize_t L = write(comfd, buff, length);
- if((size_t)L != length){
- /// " !"
- WARN("Write error!");
- return 1;
- }
- return 0;
-}
-
-
-/**
- * Safely convert data from string to double
- *
- * @param num (o) - double number read from string
- * @param str (i) - input string
- * @return 1 if success, 0 if fails
- */
-int str2double(double *num, const char *str){
- double res;
- char *endptr;
- if(!str) return 0;
- res = strtod(str, &endptr);
- if(endptr == str || *str == '\0' || *endptr != '\0'){
- /// " double!"
- WARNX("Wrong double number format!");
- return FALSE;
- }
- if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number
- return TRUE;
-}
diff --git a/fli_control/usefull_macros.h b/fli_control/usefull_macros.h
deleted file mode 100644
index 5f80b9f..0000000
--- a/fli_control/usefull_macros.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * usefull_macros.h - a set of usefull macros: memory, color etc
- *
- * Copyright 2013 Edward V. Emelianoff
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#pragma once
-#ifndef __USEFULL_MACROS_H__
-#define __USEFULL_MACROS_H__
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#if defined GETTEXT_PACKAGE && defined LOCALEDIR
-/*
- * GETTEXT
- */
-#include
-#define _(String) gettext(String)
-#define gettext_noop(String) String
-#define N_(String) gettext_noop(String)
-#else
-#define _(String) (String)
-#define N_(String) (String)
-#endif
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-// unused arguments with -Wall -Werror
-#define _U_ __attribute__((__unused__))
-
-/*
- * Coloured messages output
- */
-#define RED "\033[1;31;40m"
-#define GREEN "\033[1;32;40m"
-#define OLDCOLOR "\033[0;0;0m"
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-/*
- * ERROR/WARNING messages
- */
-extern int globErr;
-extern void signals(int sig);
-#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0)
-#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0)
-#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0)
-#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0)
-
-/*
- * print function name, debug messages
- * debug mode, -DEBUG
- */
-#ifdef EBUG
- #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
- #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, "\n");} while(0)
-#else
- #define FNAME() do{}while(0)
- #define DBG(...) do{}while(0)
-#endif //EBUG
-
-/*
- * Memory allocation
- */
-#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
-#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type)))
-#define FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0)
-
-#ifndef DBL_EPSILON
-#define DBL_EPSILON (2.2204460492503131e-16)
-#endif
-
-double dtime();
-
-// functions for color output in tty & no-color in pipes
-extern int (*red)(const char *fmt, ...);
-extern int (*_WARN)(const char *fmt, ...);
-extern int (*green)(const char *fmt, ...);
-void * my_alloc(size_t N, size_t S);
-void initial_setup();
-
-// mmap file
-typedef struct{
- char *data;
- size_t len;
-} mmapbuf;
-mmapbuf *My_mmap(char *filename);
-void My_munmap(mmapbuf *b);
-
-void restore_console();
-void setup_con();
-int read_console();
-int mygetchar();
-
-void restore_tty();
-void tty_init(char *comdev);
-size_t read_tty(uint8_t *buff, size_t length);
-int write_tty(uint8_t *buff, size_t length);
-
-int str2double(double *num, const char *str);
-
-#endif // __USEFULL_MACROS_H__