From c6042830246011bd43ddcf116656c45088cb7d80 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Mon, 7 Dec 2020 19:49:16 +0300 Subject: [PATCH] rebuild fli_control. add image view --- fli_control/CMakeLists.txt | 45 +- fli_control/FLI_control.cflags | 1 + fli_control/FLI_control.config | 8 + fli_control/FLI_control.creator | 1 + fli_control/FLI_control.creator.user | 167 ++++ fli_control/FLI_control.cxxflags | 1 + fli_control/FLI_control.files | 13 + fli_control/FLI_control.includes | 1 + fli_control/cmdlnopts.c | 53 +- fli_control/cmdlnopts.h | 9 +- fli_control/events.c | 199 +++++ fli_control/events.h | 42 + fli_control/flifunc.c | 817 ++++++++++++++++++ fli_control/flifunc.h | 60 ++ fli_control/imageview.c | 463 ++++++++++ fli_control/imageview.h | 91 ++ .../locale/ru/LC_MESSAGES/fli_control.mo | Bin 338 -> 6513 bytes fli_control/locale/ru/messages.po | 401 ++++----- fli_control/locale/ru/ru.po | 391 ++++----- fli_control/locale/ru/ru.po.bkp | 372 ++++++++ fli_control/main.c | 744 +--------------- fli_control/main.h | 72 -- fli_control/parseargs.c | 497 ----------- fli_control/parseargs.h | 124 --- fli_control/usefull_macros.c | 369 -------- fli_control/usefull_macros.h | 138 --- 26 files changed, 2635 insertions(+), 2444 deletions(-) create mode 100644 fli_control/FLI_control.cflags create mode 100644 fli_control/FLI_control.config create mode 100644 fli_control/FLI_control.creator create mode 100644 fli_control/FLI_control.creator.user create mode 100644 fli_control/FLI_control.cxxflags create mode 100644 fli_control/FLI_control.files create mode 100644 fli_control/FLI_control.includes create mode 100644 fli_control/events.c create mode 100644 fli_control/events.h create mode 100644 fli_control/flifunc.c create mode 100644 fli_control/flifunc.h create mode 100644 fli_control/imageview.c create mode 100644 fli_control/imageview.h create mode 100644 fli_control/locale/ru/ru.po.bkp delete mode 100644 fli_control/main.h delete mode 100644 fli_control/parseargs.c delete mode 100644 fli_control/parseargs.h delete mode 100644 fli_control/usefull_macros.c delete mode 100644 fli_control/usefull_macros.h 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 1a0f90bc3bd6b71004d9bc78f07d5888f22994f8..a85c6aee84e97c0337d4eb1b9f9e255e92f0709e 100644 GIT binary patch literal 6513 zcmbVPTWlOx89qR0+AS@;K}%`rNn1DG*6YOdg6k$Bj_o8SzC=lykfK(Mz2o&XyEA5H z)=r942~nh02p*vDhJY6yP^l0gfe=C-XD9Y#cW2f!vsv%Db=883M4Q&?g`z$nzW?lu z*Um-Ij(ql;bLKzi{Fm?l&+*C)n|{LZ45QtK_RJ?4%K+cpgdaT5UcuO%z~_Kp1ik?L zEN}sMHE;=dBk=FQn}GiYZUJ7inXwyy+kl@3?g3s8JPxG!C!+qhfnP%Z2SBktkmfB! z-*M?*d8wXF$^9*Fe(aFTl?M zOF**YH6Z!nU%=aeH(u48*9D|~cLB-1(Fnf5i$X`SB!?*X0xb^*@=+ktmLxod#? zfsX@^0`ZCc0eB1WufPsqEy7K3F7>-2d;)kY`rikVzkUTI{q5*`6-f4e5=N4Kw??=F zcnA7V0Jj03211m*2)rBkXCT@23XtNo3dA4V3}vqc-UK8++yx}NdVy`gNg(<0hrs)Q zzX0w6mZI-hV=~3D3rOqqfZ|_KR*m4eMW(#$25@q_$-j@|0R&@ISs@gYv700e*;KnneNdB{dwBI6-^!+E0U14+-H0#m?0 zMdPmn@yGsyABxxYP$~)R1=9QzK(hZiAjRS5z}-L_NIbg&o06Zl0dv4zKv0Uk03;s# z5!eH)MR)@iqyBJ&&jM+m(?Igqt3dM46>tj0?`9zJ?-Ag=z{h~3|M!4ffxicm-pfFm zcQuTq@!No8S3i)}KL#W{^FV}}Jp&{jJs;sLkk)?_NOCvB*`2_9fX9H30_pp2fE33i zAWUNK06T!2F-ZP>07&sZ3IxqqKN_vK32pt;i%wrOK=Vh!H^ea4(R2H-JXAlb=wQ#B%_@51~;G zP(Bgo9z=uN1;2<3UqRz&2qF728s#U&n(8?{pp2+VqJy9PXjGHPuMeQb&%=13*wI5= zr03IUJJ5#F_MzR6){RCnd;~3l7C(FNLR=!gcA=VsEt~G(_(`_jNJ5#Gxv8~Q>XUM^ zF7d5x#?}s=)^d`f@-~C@N$OUU)ABr*H|3LCq7g&F{0Sv1qd#Tlb#!#Bz}wOZ)~^^- zS!kf-q>PNYd~`}y_YLtGMNMlnY(UpForYs8cv?2)aq5{S=>; zb&_ZT_9V3G; zidJ(p_9*!vQhY+!a(p{2LAoE;@_bzIk`iZ3Gba(`EL;UjN-9V(W@uTEwG|sForcJ` zrc+WPa4;TZ5vyh}OBGE1hVeKX&uUmQN#p$^m&lzQ15 zrwOo(0=-pCGNJ);;FPXqU}?12Iwe^AMar9SJk#Z7DmJMo7|)dn_z)GwV0u2*SDaKR zhWiKi?dQ8Ga1XA9@e*P~qsJ~Oh5Fu|iVrVlT)LoKkVP4t_a%kw2HsHEE|9!zzBQ){ zVo*_{^txzz&S*-Bs@p0OqU4&B$lFOdJH_DcF)9XGc^ajvU6#ftd1@NTJC5@S;|fw3 zGN{g%q4SJ{Lz9RrpTt?NLdw*YOh(pGf>FC~Ql#z-B}dU)dCXzEaOsHOT*5_Awd-&c*hlcn_@9+TMF)-XaIJCRBzyHv{;lsNis%G*yty4#2 zDc8e?dPnv>N}B8#8rq#zIyF7hl7R-pgTn(YwYxgEC;E`qNZiyB@VJNLqF`>r9Y9eZ z;p3B%j_~h1p())dy(LI`O~`s`Kpodm+A=-78+5_-h;C4UU97qVUhueA^xPH8br$(c z#h~IfoYRgY?ogK!saVxU9bXOJu)><>^VJXEO)%d+=ahLjpL4f zQLE%M9N(*1uD6A)dL^4X4R6l3&e_=eGS{e8-|SlTjF5DeCS`cu^Fxs zZ`r);%~$!xy}~74UYZT|WU zn>4g}4W4rC=&HruUUue+7WXQ?U9d}J!kWde)q~KlpXE)j1S?KhhtbYrf_>l=oU&&_ zvSf>k*6UCJo~$^5>LH{9q}v&1zUqryfEpFg4@LbiT1COXSW@u9p_?6?9SJ33?=}C8SYt`^ z@Jh2Gb(+aM%L?9{RcrbVoOPhsvQ;S}>5z$*>(&=UN`XWTtLWE-kEu$q*ksjpk;f(4i-aag$7rgpyYLc0WMw6$|b9??3|^$U#b~U zy7}Q1p-r-a6=Go+xX9+BTx{k3X5fjRlJ~N7f|>GwV(vmRm`A@ z3#w2ZDcdMy7(Wx$zSv+3CTBQ6r2W(iPJXkyC3N=TZIXEvuvVn?I z2)c?Sh>kVb*D}Jv{Srxzq^aAuT&_96n|sABh87E*3W}b1zvK9SLxj3AI{TWYwTATpvjacQg+V$cVD$dS^ujc5oXdkq6b6 z;n*4q0TQxO4T|e+A`@%%0DdX+DgpsFAiFI7;ALc8r*W}pcM4}d@kJbVta`bk$lGgt z-ttist%bNICS!4mJhrY2UV=?j5mHfMs6}-FMTm;~isM%KCF+9shcK!N8`c$NV7=Mx zWv5hfnry9a5RHl)M>Di12YRV!8*Im&iHVE2sYmvI2sP%}diq-dQh wpgg3G!iZXZ*|NhVL#d$Sd1FFRt~Advgx@22!ZO!hM!b3GJM;6lFRriu1+tUlJpcdz delta 66 xcmexpbcxC0o)F7a1|VPrVi_P-0b*t#)&XJ=umEBSprj>`2C0F8%^Ufo7y%Gt20;J- 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__