From 3113d9754d7784f43f791e77ffba91a4200ddc6d Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Mon, 25 Dec 2023 16:21:27 +0300 Subject: [PATCH] add image counter, `infty` mode, make some faster --- CMakeLists.txt | 9 +-- basestructs.h | 1 + ccdfunc.c | 15 ++-- client.c | 19 ++++-- cmdlnopts.c | 4 +- cmdlnopts.h | 1 + imageview.c | 31 ++++++--- locale/ru/messages.po | 154 ++++++++++++++++++++++-------------------- locale/ru/ru.po | 154 ++++++++++++++++++++++-------------------- server.c | 52 ++++++++++---- server.h | 1 + socket.h | 2 +- 12 files changed, 253 insertions(+), 190 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71bef5f..4723d72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.20) set(PROJ ccd_capture) -set(MINOR_VERSION "0") -set(MID_VERSION "1") set(MAJOR_VERSION "1") +set(MID_VERSION "1") +set(MINOR_VERSION "1") set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}") project(${PROJ} VERSION ${VERSION} LANGUAGES C) @@ -52,8 +52,9 @@ if(DEBUG) set(CMAKE_BUILD_TYPE DEBUG) set(CMAKE_VERBOSE_MAKEFILE "ON") else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -march=native -fdata-sections -ffunction-sections -flto") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -flto") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -march=native -fdata-sections -ffunction-sections -flto=auto") +# add_definitions(-DEBUG) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -flto=auto") set(CMAKE_BUILD_TYPE RELEASE) endif() diff --git a/basestructs.h b/basestructs.h index 7dbcc47..7b62011 100644 --- a/basestructs.h +++ b/basestructs.h @@ -32,6 +32,7 @@ typedef struct __attribute__((packed, aligned(4))){ uint16_t max, min; // min/max values float avr, std; // statistics size_t bytelen; // size of image in bytes + size_t imnumber; // counter of images captured from server's start void *data; // pointer to data (next byte after this struct) - only for server /* `data` is uint8_t or uint16_t depending on `bitpix` */ } IMG; diff --git a/ccdfunc.c b/ccdfunc.c index cc51618..f41d958 100644 --- a/ccdfunc.c +++ b/ccdfunc.c @@ -898,13 +898,14 @@ void framerate(){ tlast = t; } -static volatile int grabno = 0, lastgrabno = 0, exitgrab = FALSE; +static volatile int exitgrab = FALSE; +static volatile size_t lastgrabno = 0; static void *grabnext(void *arg){ FNAME(); IMG *ima = (IMG*) arg; do{ if(exitgrab) return NULL; - TIMESTAMP("Start exp #%d", grabno+1); + TIMESTAMP("Start next exp"); TIMEINIT(); if(!ima || !camera) return NULL; if(!camera->startexposition()){ @@ -922,9 +923,9 @@ static void *grabnext(void *arg){ if(cs != CAPTURE_READY){ WARNX(_("Some error when capture")); return NULL;} TIMESTAMP("get"); if(!camera->capture(ima)){ WARNX(_("Can't grab image")); continue; } + ++ima->imnumber; //calculate_stat(ima); TIMESTAMP("OK"); - ++grabno; }while(1); } @@ -973,9 +974,11 @@ int ccdcaptured(IMG **imgptr){ grabthread = 0; } }else{ // grab in process - if(grabno != lastgrabno){ // done - lastgrabno = grabno; - TIMESTAMP("Got exp #%d", grabno); + if(ima->imnumber != lastgrabno){ // done + /*ssize_t delta = ima->imnumber - lastgrabno; + if(delta > 0 && delta != 1) WARNX("ccdcaptured(): missed %zd images", delta-1);*/ + lastgrabno = ima->imnumber; + TIMESTAMP("Got exp #%zd", lastgrabno); framerate(); return TRUE; } diff --git a/client.c b/client.c index c002ed9..6eb5d4b 100644 --- a/client.c +++ b/client.c @@ -101,7 +101,7 @@ static int parseans(char *ans){ sscanf(val, "%d,%d,%d,%d", &xc0, &yc0, &xc1, &yc1); DBG("Got current format: %d,%d,%d,%d", xc0, yc0, xc1, yc1); return TRUE; - } + }else if(0 == strcmp(CMD_INFTY, ans)) return TRUE; /* #ifdef IMAGEVIEW else if(0 == strcmp(CMD_IMWIDTH, ans)){ @@ -245,6 +245,7 @@ void client(int sock){ SENDCMDW(CMD_RESTART); return; } + if(GP->infty > -1) SENDMSGW(CMD_INFTY, "=%d", GP->infty); send_headers(sock); double t0 = dtime(), tw = t0; int Nremain = 0, nframe = 1; @@ -255,7 +256,9 @@ void client(int sock){ else GP->waitexpend = TRUE; // N>1 - wait for exp ends SENDMSGW(CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); }else{ - getans(sock, NULL); + int cntr = 0; + while(dtime() - t0 < WAIT_TIMEOUT && cntr < 10) + if(!getans(sock, NULL)) ++cntr; DBG("RETURN: no more data"); return; } @@ -389,8 +392,8 @@ static void getimage(){ } if(ima.timestamp != oldtimestamp){ // test if image is really new oldtimestamp = ima.timestamp; - TIMESTAMP("Got image"); - ++grabno; + grabno = ima.imnumber; + TIMESTAMP("Got image #%zd", ima.imnumber); }else WARNX("Still got old image"); eofg: if(!shmima) close(imsock); @@ -403,7 +406,7 @@ static void *grabnext(void _U_ *arg){ // daemon grabbing images through the net while(1){ if(!getWin()) exit(1); expstate = CAMERA_CAPTURE; - TIMESTAMP("End of cycle, start new #%d", grabno+1); + TIMESTAMP("End of cycle, start new"); TIMEINIT(); SENDMSGW(CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); // start capture double timeout = GP->exptime + CLIENT_TIMEOUT, t0 = dtime(); @@ -443,7 +446,7 @@ static void *waitimage(void _U_ *arg){ // passive waiting for next image usleep(1000); continue; } - TIMESTAMP("End of cycle, start new #%d", grabno+1); + TIMESTAMP("End of cycle, start new"); TIMEINIT(); getimage(); expstate = CAMERA_IDLE; @@ -487,7 +490,9 @@ int sockcaptured(IMG **imgptr){ if(grabno != oldgrabno){ // image is ready TIMESTAMP("Image #%d ready", grabno); if(*imgptr && (*imgptr != &ima)) free(*imgptr); - *imgptr = &ima; + *imgptr = &ima; /* + ssize_t delta = ima.imnumber - oldgrabno; + if(delta > 0 && delta != 1) WARNX("sockcaptured(): missed %zd images", delta-1);*/ oldgrabno = grabno; framerate(); //TIMESTAMP("sockcaptured() end, return TRUE"); diff --git a/cmdlnopts.c b/cmdlnopts.c index 8f92cb9..8b586f0 100644 --- a/cmdlnopts.c +++ b/cmdlnopts.c @@ -30,7 +30,8 @@ static glob_pars G = { .brightness = NAN, .gain = NAN, .setwheel = -1, .fanspeed = -1, - .shmkey = 7777777 + .shmkey = 7777777, + .infty = -1 }; /* @@ -105,6 +106,7 @@ myoption cmdlnopts[] = { {"shmkey", NEED_ARG, NULL, 'k', arg_int, APTR(&G.shmkey), N_("shared memory (with image data) key (default: 7777777")}, {"forceimsock",NO_ARGS, &G.forceimsock,1, arg_none, NULL, N_("force using image through socket transition even if can use SHM")}, + {"infty", NEED_ARG, NULL, 0, arg_int, APTR(&G.infty), N_("start (!=0) or stop(==0) infinity capturing loop")}, #ifdef IMAGEVIEW {"display", NO_ARGS, NULL, 'D', arg_int, APTR(&G.showimage), N_("Display image in OpenGL window")}, diff --git a/cmdlnopts.h b/cmdlnopts.h index d60c463..3ed6130 100644 --- a/cmdlnopts.h +++ b/cmdlnopts.h @@ -71,6 +71,7 @@ typedef struct{ int showimage; // show image preview int shmkey; // shared memory (with image data) key int forceimsock; // force using image through socket transition even if can use SHM + int infty; // run (==1) or stop (==0) infinity loop float gain; // gain level (only for CMOS) float brightness; // brightness (only for CMOS) double exptime; // time of exposition in seconds diff --git a/imageview.c b/imageview.c index 005b9d3..953719a 100644 --- a/imageview.c +++ b/imageview.c @@ -28,7 +28,7 @@ #include "imageview.h" #include "events.h" #include "omp.h" -//#include "socket.h" // for timestamp +#include "socket.h" // for timestamp windowData *win = NULL; // main window (common variable for events.c) static pthread_t GLUTthread = 0; // main GLUT thread @@ -198,9 +198,10 @@ static void renderBitmapString(float x, float y, void *font, char *string, GLuby }*/ static void RedrawWindow(){ +//double t0 = dtime(); //DBG("ini=%d, win=%s", initialized, win ? "yes" : "no"); if(!initialized || !win || win->killthread) return; - if(pthread_mutex_trylock(&win->mutex)) 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); @@ -211,6 +212,7 @@ static void RedrawWindow(){ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, win->Tex); if(win->image->changed){ + pthread_mutex_lock(&win->mutex); 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, @@ -218,6 +220,7 @@ static void RedrawWindow(){ /* 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; + pthread_mutex_unlock(&win->mutex); } w /= 2.f; h /= 2.f; float lr = 1., ud = -1.; // flipping coefficients (mirror image around Y by default) @@ -232,7 +235,8 @@ static void RedrawWindow(){ glDisable(GL_TEXTURE_2D); glFinish(); glutSwapBuffers(); - pthread_mutex_unlock(&win->mutex); + //pthread_mutex_unlock(&win->mutex); +//DBG("redraw: %gs", dtime()-t0); usleep(1000); } @@ -520,6 +524,7 @@ static uint8_t *mkcuts(IMG *img, int w, int h){ int s = w*h; double sum = 0., sum2 = 0.; int bytes = getNbytes(img); + TIMESTAMP("Make histogram"); if(bytes == 1){ uint8_t *data = (uint8_t*) img->data; #pragma omp parallel @@ -561,7 +566,7 @@ static uint8_t *mkcuts(IMG *img, int w, int h){ } } } - + TIMESTAMP("Calculate stat"); //WARNX("histo: %gs", dtime()-t0); // get median level int counts = s/2, median = 0, max = (bytes == 1) ? 0xff : 0xffff; @@ -578,6 +583,7 @@ static uint8_t *mkcuts(IMG *img, int w, int h){ // now we can recalculate values: new = (old - low)*A //WARNX("stat: %gs", dtime()-t0); // DEBUG: 2ms without OMP; 0.7ms with + TIMESTAMP("apply cuts"); if(bytes == 1){ uint8_t *data = (uint8_t*) img->data; OMP_FOR() @@ -603,18 +609,26 @@ static uint8_t *mkcuts(IMG *img, int w, int h){ static void change_displayed_image(IMG *img){ if(!win || !img) return; - pthread_mutex_lock(&win->mutex); + static size_t lastN = 0; + ssize_t delta = img->imnumber - lastN; + TIMESTAMP("Got image #%zd", img->imnumber); + if(delta > 0 && delta != 1) WARNX("Missed %zd images", delta-1); + lastN = img->imnumber; + //pthread_mutex_lock(&win->mutex); rawimage *im = win->image; DBG("imh=%d, imw=%d, ch=%u, cw=%u", im->h, im->w, img->h, img->w); int w = img->w, h = img->h, s = w*h; if(!im || (im->h != h) || (im->w != w)){ // realloc image to new size + pthread_mutex_lock(&win->mutex); DBG("\n\nRealloc rawdata"); if(!im) im = MALLOC(rawimage, 1); if(im->h*im->w < s) im->rawdata = realloc(im->rawdata, s*3); im->h = h; im->w = w; win->image = im; DBG("win->image changed"); + pthread_mutex_unlock(&win->mutex); } + TIMESTAMP("level correction"); uint8_t *newima; if(imequalize){ DBG("equalize"); @@ -624,6 +638,7 @@ static void change_displayed_image(IMG *img){ newima = mkcuts(img, w, h); } GLubyte *dst = im->rawdata; + TIMESTAMP("colorfun"); //double t0 = dtime(); if(ft < COLORFN_LINEAR){ // gray // without OMP: 1.8ms; with OMP: 0.8ms @@ -657,7 +672,7 @@ static void change_displayed_image(IMG *img){ }*/ DBG("Unlock"); win->image->changed = 1; - pthread_mutex_unlock(&win->mutex); + //pthread_mutex_unlock(&win->mutex); } void closeGL(){ // killed by external signal or ctrl+c @@ -703,10 +718,10 @@ int viewer(imagefunc newimage){ if((win->winevt & WINEVT_GETIMAGE) || !(win->winevt & WINEVT_PAUSE)){ //DBG("CHK new image, t=%g", dtime()-t0); if(newimage(&img)){ - //TIMESTAMP("got image -> change"); + TIMESTAMP("got image -> change"); win->winevt &= ~WINEVT_GETIMAGE; change_displayed_image(img); // change image if refreshed - //TIMESTAMP("changed"); + TIMESTAMP("changed"); } //DBG("Next cycle, t=%g", dtime()-t0); } diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 5ce6694..15446ac 100644 --- a/locale/ru/messages.po +++ b/locale/ru/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-12-21 16:46+0300\n" +"POT-Creation-Date: 2023-12-25 16:15+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,243 +17,247 @@ msgstr "" "Content-Type: text/plain; charset=koi8-r\n" "Content-Transfer-Encoding: 8bit\n" -#: cmdlnopts.c:41 +#: cmdlnopts.c:42 msgid "common device plugin (e.g devfli.so)" msgstr "" -#: cmdlnopts.c:42 +#: cmdlnopts.c:43 msgid "camera device plugin (e.g. devfli.so)" msgstr "" -#: cmdlnopts.c:43 +#: cmdlnopts.c:44 msgid "focuser device plugin (e.g. devzwo.so)" msgstr "" -#: cmdlnopts.c:44 +#: cmdlnopts.c:45 msgid "wheel device plugin (e.g. devdummy.so)" msgstr "" -#: cmdlnopts.c:45 +#: cmdlnopts.c:46 msgid "list connected devices" msgstr "" -#: cmdlnopts.c:46 +#: cmdlnopts.c:47 msgid "camera device number (if many: 0, 1, 2 etc)" msgstr "" -#: cmdlnopts.c:47 +#: cmdlnopts.c:48 msgid "filter wheel device number (if many: 0, 1, 2 etc)" msgstr "" -#: cmdlnopts.c:48 +#: cmdlnopts.c:49 msgid "focuser device number (if many: 0, 1, 2 etc)" msgstr "" -#: cmdlnopts.c:49 +#: cmdlnopts.c:50 msgid "show this help" msgstr "" -#: cmdlnopts.c:50 +#: cmdlnopts.c:51 msgid "rewrite output file if exists" msgstr "" -#: cmdlnopts.c:51 +#: cmdlnopts.c:52 msgid "verbose level (-V - messages, -VV - debug, -VVV - all shit)" msgstr "" -#: cmdlnopts.c:52 +#: cmdlnopts.c:53 msgid "not open shutter, when exposing (\"dark frames\")" msgstr "" -#: cmdlnopts.c:53 +#: cmdlnopts.c:54 msgid "run in 8-bit mode" msgstr "" -#: cmdlnopts.c:54 +#: cmdlnopts.c:55 msgid "fast readout mode" msgstr "" -#: cmdlnopts.c:55 +#: cmdlnopts.c:56 msgid "set CCD temperature to given value (degr C)" msgstr "" -#: cmdlnopts.c:56 +#: cmdlnopts.c:57 msgid "set fan speed (0 - off, 1 - low, 2 - high)" msgstr "" -#: cmdlnopts.c:58 +#: cmdlnopts.c:59 msgid "program author" msgstr "" -#: cmdlnopts.c:59 +#: cmdlnopts.c:60 msgid "object type (neon, object, flat etc)" msgstr "" -#: cmdlnopts.c:60 +#: cmdlnopts.c:61 msgid "instrument name" msgstr "" -#: cmdlnopts.c:61 +#: cmdlnopts.c:62 msgid "object name" msgstr "" -#: cmdlnopts.c:62 +#: cmdlnopts.c:63 msgid "observers' names" msgstr "" -#: cmdlnopts.c:63 +#: cmdlnopts.c:64 msgid "observing program name" msgstr "" -#: cmdlnopts.c:64 +#: cmdlnopts.c:65 msgid "add records to header from given file[s]" msgstr "" -#: cmdlnopts.c:65 +#: cmdlnopts.c:66 msgid "output file name" msgstr "" -#: cmdlnopts.c:66 +#: cmdlnopts.c:67 msgid "wait while exposition ends" msgstr "" -#: cmdlnopts.c:68 +#: cmdlnopts.c:69 msgid "N flushes before exposing (default: 1)" msgstr "" -#: cmdlnopts.c:69 +#: cmdlnopts.c:70 msgid "horizontal binning to N pixels" msgstr "" -#: cmdlnopts.c:70 +#: cmdlnopts.c:71 msgid "vertical binning to N pixels" msgstr "" -#: cmdlnopts.c:71 +#: cmdlnopts.c:72 msgid "make series of N frames" msgstr "" -#: cmdlnopts.c:72 +#: cmdlnopts.c:73 msgid "make pause for N seconds between expositions" msgstr "" -#: cmdlnopts.c:73 +#: cmdlnopts.c:74 msgid "set exposure time to given value (seconds!)" msgstr "" -#: cmdlnopts.c:74 +#: cmdlnopts.c:75 msgid "cancel current exposition" msgstr "" -#: cmdlnopts.c:75 +#: cmdlnopts.c:76 msgid "" "absolute (not divided by binning!) frame X0 coordinate (-1 - all with " "overscan)" msgstr "" -#: cmdlnopts.c:76 +#: cmdlnopts.c:77 msgid "absolute frame Y0 coordinate (-1 - all with overscan)" msgstr "" -#: cmdlnopts.c:77 +#: cmdlnopts.c:78 msgid "absolute frame X1 coordinate (-1 - all with overscan)" msgstr "" -#: cmdlnopts.c:78 +#: cmdlnopts.c:79 msgid "absolute frame Y1 coordinate (-1 - all with overscan)" msgstr "" -#: cmdlnopts.c:80 +#: cmdlnopts.c:81 msgid "open shutter" msgstr "" -#: cmdlnopts.c:81 +#: cmdlnopts.c:82 msgid "close shutter" msgstr "" -#: cmdlnopts.c:82 +#: cmdlnopts.c:83 msgid "run exposition on LOW @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:83 +#: cmdlnopts.c:84 msgid "run exposition on HIGH @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:84 +#: cmdlnopts.c:85 msgid "get value of I/O port pins" msgstr "" -#: cmdlnopts.c:85 +#: cmdlnopts.c:86 msgid "move stepper motor asynchronous" msgstr "" -#: cmdlnopts.c:87 +#: cmdlnopts.c:88 msgid "set I/O port pins to given value (decimal number, pin1 is LSB)" msgstr "" -#: cmdlnopts.c:88 +#: cmdlnopts.c:89 msgid "" "configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == " "output, 0 == input)" msgstr "" -#: cmdlnopts.c:90 +#: cmdlnopts.c:91 msgid "move focuser to absolute position, mm" msgstr "" -#: cmdlnopts.c:91 +#: cmdlnopts.c:92 msgid "move focuser to relative position, mm (only for standalone)" msgstr "" -#: cmdlnopts.c:93 +#: cmdlnopts.c:94 msgid "set wheel position" msgstr "" -#: cmdlnopts.c:95 +#: cmdlnopts.c:96 msgid "CMOS gain level" msgstr "" -#: cmdlnopts.c:96 +#: cmdlnopts.c:97 msgid "CMOS brightness level" msgstr "" -#: cmdlnopts.c:98 +#: cmdlnopts.c:99 msgid "logging file name (if run as server)" msgstr "" -#: cmdlnopts.c:99 +#: cmdlnopts.c:100 msgid "UNIX socket name (command socket)" msgstr "" -#: cmdlnopts.c:100 +#: cmdlnopts.c:101 msgid "local INET command socket port" msgstr "" -#: cmdlnopts.c:101 +#: cmdlnopts.c:102 msgid "INET image socket port" msgstr "" -#: cmdlnopts.c:102 +#: cmdlnopts.c:103 msgid "run as client" msgstr "" -#: cmdlnopts.c:103 +#: cmdlnopts.c:104 msgid "passive viewer (only get last images)" msgstr "" -#: cmdlnopts.c:104 +#: cmdlnopts.c:105 msgid "restart image server" msgstr "" -#: cmdlnopts.c:106 +#: cmdlnopts.c:107 msgid "shared memory (with image data) key (default: 7777777" msgstr "" -#: cmdlnopts.c:107 +#: cmdlnopts.c:108 msgid "force using image through socket transition even if can use SHM" msgstr "" -#: cmdlnopts.c:110 +#: cmdlnopts.c:109 +msgid "start (!=0) or stop(==0) infinity capturing loop" +msgstr "" + +#: cmdlnopts.c:112 msgid "Display image in OpenGL window" msgstr "" @@ -486,12 +490,12 @@ msgstr "" msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:767 server.c:262 +#: ccdfunc.c:767 server.c:265 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:779 server.c:263 +#: ccdfunc.c:779 server.c:266 msgid "Can't set given geometry" msgstr "" @@ -537,7 +541,7 @@ msgstr "" msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:826 ccdfunc.c:911 server.c:148 +#: ccdfunc.c:826 ccdfunc.c:912 server.c:149 msgid "Can't start exposition" msgstr "" @@ -549,29 +553,29 @@ msgstr "" msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:838 ccdfunc.c:924 +#: ccdfunc.c:838 ccdfunc.c:925 msgid "Can't grab image" msgstr "" #. %d секунд до окончания паузы\n -#: ccdfunc.c:850 client.c:294 +#: ccdfunc.c:850 client.c:297 #, c-format msgid "%d seconds till pause ends\n" msgstr "" -#: ccdfunc.c:922 +#: ccdfunc.c:923 msgid "Some error when capture" msgstr "" -#: server.c:196 +#: server.c:189 msgid "No camera device" msgstr "" -#: client.c:279 +#: client.c:282 msgid "Can't make exposition" msgstr "" -#: client.c:310 +#: client.c:313 msgid "Server timeout" msgstr "" @@ -579,28 +583,28 @@ msgstr "" msgid "Already initialized!" msgstr "" -#: imageview.c:308 +#: imageview.c:312 msgid "Can't init mutex!" msgstr "" -#: imageview.c:421 +#: imageview.c:425 #, c-format msgid "Histogram conversion: %s" msgstr "" -#: imageview.c:689 +#: imageview.c:704 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "" -#: imageview.c:731 +#: imageview.c:746 #, c-format msgid "Equalization of histogram: %s" msgstr "" -#: imageview.c:731 +#: imageview.c:746 msgid "on" msgstr "" -#: imageview.c:731 +#: imageview.c:746 msgid "off" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 4331cbc..1d552e6 100644 --- a/locale/ru/ru.po +++ b/locale/ru/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2023-12-21 16:40+0300\n" + "POT-Creation-Date: 2023-12-25 15:48+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -22,7 +22,7 @@ msgid "%.1f seconds till exposition ends" msgstr "%.1f " #. %d секунд до окончания паузы\n -#: ccdfunc.c:850 client.c:294 +#: ccdfunc.c:850 client.c:297 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d \n" @@ -31,11 +31,11 @@ msgstr "%d msgid "Already initialized!" msgstr " !" -#: cmdlnopts.c:96 +#: cmdlnopts.c:97 msgid "CMOS brightness level" msgstr " CMOS" -#: cmdlnopts.c:95 +#: cmdlnopts.c:96 msgid "CMOS gain level" msgstr " Gain CMOS" @@ -105,7 +105,7 @@ msgstr " msgid "Can't get max wheel position" msgstr " " -#: ccdfunc.c:838 ccdfunc.c:924 +#: ccdfunc.c:838 ccdfunc.c:925 msgid "Can't grab image" msgstr " " @@ -113,15 +113,15 @@ msgstr " msgid "Can't home focuser" msgstr " " -#: imageview.c:308 +#: imageview.c:312 msgid "Can't init mutex!" msgstr " !" -#: client.c:279 +#: client.c:282 msgid "Can't make exposition" msgstr " " -#: imageview.c:689 +#: imageview.c:704 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr " OpenGL, " @@ -162,7 +162,7 @@ msgstr " msgid "Can't set active wheel number" msgstr " " -#: ccdfunc.c:767 server.c:262 +#: ccdfunc.c:767 server.c:265 #, c-format msgid "Can't set binning %dx%d" msgstr " %dx%d" @@ -190,7 +190,7 @@ msgstr " msgid "Can't set gain to %g" msgstr " Gain %g" -#: ccdfunc.c:779 server.c:263 +#: ccdfunc.c:779 server.c:266 msgid "Can't set given geometry" msgstr " " @@ -213,7 +213,7 @@ msgstr " msgid "Can't set wheel position %d" msgstr " %d" -#: ccdfunc.c:826 ccdfunc.c:911 server.c:148 +#: ccdfunc.c:826 ccdfunc.c:912 server.c:149 msgid "Can't start exposition" msgstr " " @@ -228,11 +228,11 @@ msgstr " msgid "Current format: %s" msgstr "" -#: cmdlnopts.c:110 +#: cmdlnopts.c:112 msgid "Display image in OpenGL window" msgstr " OpenGL" -#: imageview.c:731 +#: imageview.c:746 #, c-format msgid "Equalization of histogram: %s" msgstr " : %s" @@ -275,12 +275,12 @@ msgstr " msgid "Full array: %s" msgstr " : %s" -#: imageview.c:421 +#: imageview.c:425 #, c-format msgid "Histogram conversion: %s" msgstr " : %s" -#: cmdlnopts.c:101 +#: cmdlnopts.c:102 #, fuzzy msgid "INET image socket port" msgstr " " @@ -290,11 +290,11 @@ msgstr " msgid "Image stat:\n" msgstr " : \n" -#: cmdlnopts.c:68 +#: cmdlnopts.c:69 msgid "N flushes before exposing (default: 1)" msgstr "N ( : 1)" -#: server.c:196 +#: server.c:189 msgid "No camera device" msgstr " " @@ -328,7 +328,7 @@ msgstr " msgid "Readout mode: %s" msgstr " : %s" -#: client.c:310 +#: client.c:313 msgid "Server timeout" msgstr " " @@ -352,7 +352,7 @@ msgstr " msgid "Shutter command: %s\n" msgstr " : %s\n" -#: ccdfunc.c:922 +#: ccdfunc.c:923 msgid "Some error when capture" msgstr "" @@ -368,7 +368,7 @@ msgstr " msgid "Try to write %d to I/O port" msgstr " %d I/O" -#: cmdlnopts.c:99 +#: cmdlnopts.c:100 #, fuzzy msgid "UNIX socket name (command socket)" msgstr " UNIX-" @@ -382,229 +382,233 @@ msgstr " msgid "Wheel position should be from 0 to %d" msgstr " 0 %d" -#: cmdlnopts.c:75 +#: cmdlnopts.c:76 msgid "absolute (not divided by binning!) frame X0 coordinate (-1 - all " "with overscan)" msgstr " ( !) X0 (-1 - " ")" -#: cmdlnopts.c:77 +#: cmdlnopts.c:78 msgid "absolute frame X1 coordinate (-1 - all with overscan)" msgstr " X1 (-1 - )" -#: cmdlnopts.c:76 +#: cmdlnopts.c:77 msgid "absolute frame Y0 coordinate (-1 - all with overscan)" msgstr " Y0 (-1 - )" -#: cmdlnopts.c:78 +#: cmdlnopts.c:79 msgid "absolute frame Y1 coordinate (-1 - all with overscan)" msgstr " Y1 (-1 - )" -#: cmdlnopts.c:64 +#: cmdlnopts.c:65 msgid "add records to header from given file[s]" msgstr " FITS- " -#: cmdlnopts.c:46 +#: cmdlnopts.c:47 msgid "camera device number (if many: 0, 1, 2 etc)" msgstr " " -#: cmdlnopts.c:42 +#: cmdlnopts.c:43 msgid "camera device plugin (e.g. devfli.so)" msgstr " (, devfli.so)" -#: cmdlnopts.c:74 +#: cmdlnopts.c:75 msgid "cancel current exposition" msgstr " " -#: cmdlnopts.c:81 +#: cmdlnopts.c:82 msgid "close shutter" msgstr " " -#: cmdlnopts.c:41 +#: cmdlnopts.c:42 msgid "common device plugin (e.g devfli.so)" msgstr " (, devfli.so)" -#: cmdlnopts.c:88 +#: cmdlnopts.c:89 msgid "configure I/O port pins to given value (decimal number, pin1 is LSB, " "1 == output, 0 == input)" msgstr " I/O ( , " "pin1 - , 1 - , 0 - )" -#: cmdlnopts.c:54 +#: cmdlnopts.c:55 msgid "fast readout mode" msgstr " " -#: cmdlnopts.c:47 +#: cmdlnopts.c:48 msgid "filter wheel device number (if many: 0, 1, 2 etc)" msgstr " " -#: cmdlnopts.c:48 +#: cmdlnopts.c:49 msgid "focuser device number (if many: 0, 1, 2 etc)" msgstr " " -#: cmdlnopts.c:43 +#: cmdlnopts.c:44 msgid "focuser device plugin (e.g. devzwo.so)" msgstr " (, devzwo.so)" -#: cmdlnopts.c:107 +#: cmdlnopts.c:108 msgid "force using image through socket transition even if can use SHM" msgstr "" -#: cmdlnopts.c:84 +#: cmdlnopts.c:85 msgid "get value of I/O port pins" msgstr " I/O" -#: cmdlnopts.c:69 +#: cmdlnopts.c:70 msgid "horizontal binning to N pixels" msgstr " N " -#: cmdlnopts.c:60 +#: cmdlnopts.c:61 msgid "instrument name" msgstr " " -#: cmdlnopts.c:45 +#: cmdlnopts.c:46 msgid "list connected devices" msgstr " " -#: cmdlnopts.c:100 +#: cmdlnopts.c:101 #, fuzzy msgid "local INET command socket port" msgstr " " -#: cmdlnopts.c:98 +#: cmdlnopts.c:99 msgid "logging file name (if run as server)" msgstr " ( )" -#: cmdlnopts.c:72 +#: cmdlnopts.c:73 msgid "make pause for N seconds between expositions" msgstr " N " -#: cmdlnopts.c:71 +#: cmdlnopts.c:72 msgid "make series of N frames" msgstr " N " -#: cmdlnopts.c:90 +#: cmdlnopts.c:91 msgid "move focuser to absolute position, mm" msgstr " , " -#: cmdlnopts.c:91 +#: cmdlnopts.c:92 msgid "move focuser to relative position, mm (only for standalone)" msgstr " , ( /" ")" -#: cmdlnopts.c:85 +#: cmdlnopts.c:86 msgid "move stepper motor asynchronous" msgstr " " -#: cmdlnopts.c:52 +#: cmdlnopts.c:53 msgid "not open shutter, when exposing (\"dark frames\")" msgstr " (\"\")" -#: cmdlnopts.c:61 +#: cmdlnopts.c:62 msgid "object name" msgstr " " -#: cmdlnopts.c:59 +#: cmdlnopts.c:60 msgid "object type (neon, object, flat etc)" msgstr " (neon, object, flat ..)" -#: cmdlnopts.c:62 +#: cmdlnopts.c:63 msgid "observers' names" msgstr " " -#: cmdlnopts.c:63 +#: cmdlnopts.c:64 msgid "observing program name" msgstr " " -#: imageview.c:731 +#: imageview.c:746 msgid "off" msgstr "" -#: imageview.c:731 +#: imageview.c:746 msgid "on" msgstr "" -#: cmdlnopts.c:80 +#: cmdlnopts.c:81 msgid "open shutter" msgstr " " -#: cmdlnopts.c:65 +#: cmdlnopts.c:66 msgid "output file name" msgstr " " -#: cmdlnopts.c:103 +#: cmdlnopts.c:104 msgid "passive viewer (only get last images)" msgstr "" -#: cmdlnopts.c:58 +#: cmdlnopts.c:59 msgid "program author" msgstr " " -#: cmdlnopts.c:104 +#: cmdlnopts.c:105 msgid "restart image server" msgstr " " -#: cmdlnopts.c:50 +#: cmdlnopts.c:51 msgid "rewrite output file if exists" msgstr " " -#: cmdlnopts.c:102 +#: cmdlnopts.c:103 msgid "run as client" msgstr " " -#: cmdlnopts.c:83 +#: cmdlnopts.c:84 msgid "run exposition on HIGH @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:82 +#: cmdlnopts.c:83 msgid "run exposition on LOW @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:53 +#: cmdlnopts.c:54 msgid "run in 8-bit mode" msgstr "8- " -#: cmdlnopts.c:55 +#: cmdlnopts.c:56 msgid "set CCD temperature to given value (degr C)" msgstr " ()" -#: cmdlnopts.c:87 +#: cmdlnopts.c:88 msgid "set I/O port pins to given value (decimal number, pin1 is LSB)" msgstr " I/O ( , pin1 - )" -#: cmdlnopts.c:73 +#: cmdlnopts.c:74 msgid "set exposure time to given value (seconds!)" msgstr " (!)" -#: cmdlnopts.c:56 +#: cmdlnopts.c:57 msgid "set fan speed (0 - off, 1 - low, 2 - high)" msgstr " (0 - , 1 - , 2 - )" -#: cmdlnopts.c:93 +#: cmdlnopts.c:94 msgid "set wheel position" msgstr " " -#: cmdlnopts.c:106 +#: cmdlnopts.c:107 msgid "shared memory (with image data) key (default: 7777777" msgstr "" -#: cmdlnopts.c:49 +#: cmdlnopts.c:50 msgid "show this help" msgstr " " -#: cmdlnopts.c:51 +#: cmdlnopts.c:109 +msgid "start (!=0) or stop(==0) infinity capturing loop" +msgstr "" + +#: cmdlnopts.c:52 msgid "verbose level (-V - messages, -VV - debug, -VVV - all shit)" msgstr " (-V - , -VV - , -VVV - )" -#: cmdlnopts.c:70 +#: cmdlnopts.c:71 msgid "vertical binning to N pixels" msgstr " N " -#: cmdlnopts.c:66 +#: cmdlnopts.c:67 msgid "wait while exposition ends" msgstr ", " -#: cmdlnopts.c:44 +#: cmdlnopts.c:45 msgid "wheel device plugin (e.g. devdummy.so)" msgstr " (, devdummy.so)" diff --git a/server.c b/server.c index d7555e1..5fdbe55 100644 --- a/server.c +++ b/server.c @@ -37,7 +37,7 @@ static _Atomic camera_state camstate = CAMERA_IDLE; #define FLAG_STARTCAPTURE (1<<0) #define FLAG_CANCEL (1<<1) #define FLAG_RESTARTSERVER (1<<2) -static atomic_int camflags = 0, camfanspd = 0, confio = 0, nflushes; +static atomic_int camflags = 0, camfanspd = 0, confio = 0, nflushes, infty = 0; static char *outfile = NULL, *lastfile = NULL; // current output file name/prefix; last name of saved file static frameformat frmformatmax = {0}, curformat = {0}; // maximal format static void *camdev = NULL, *focdev = NULL, *wheeldev = NULL; @@ -80,6 +80,7 @@ strpair allcommands[] = { { CMD_IMHEIGHT, "last image height" }, { CMD_IMWIDTH, "last image width" }, { CMD_INFO, "connected devices state" }, + { CMD_INFTY, "an infinity loop taking images until there's connected clients" }, { CMD_INSTRUMENT, "FITS 'INSTRUME' field" }, { CMD_IO, "get/set camera IO" }, { CMD_LASTFNAME, "path to last saved file"}, @@ -107,7 +108,7 @@ static pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/ // return TRUE if `locmutex` can be locked static int lock(){ if(pthread_mutex_trylock(&locmutex)){ - DBG("\n\nAlready locked"); + //DBG("\n\nAlready locked"); return FALSE; } return TRUE; @@ -152,14 +153,6 @@ static inline void cameraidlestate(){ // idle - wait for capture commands } } static inline void cameracapturestate(){ // capturing - wait for exposition ends - if(camflags & FLAG_CANCEL){ // cancel all expositions - DBG("Cancel exposition"); - LOGMSG("User canceled exposition"); - camflags &= ~(FLAG_STARTCAPTURE | FLAG_CANCEL); - camera->cancel(); - camstate = CAMERA_IDLE; - return; - } capture_status cs; if(camera->pollcapture(&cs, &tremain)){ if(cs != CAPTURE_PROCESS){ @@ -217,6 +210,16 @@ static void* processCAM(_U_ void *d){ LOGMSG("BODYTEMP=%.1f", t); } } + if(camflags & FLAG_CANCEL){ // cancel all expositions + DBG("Cancel exposition"); + LOGMSG("User canceled exposition"); + camflags &= ~(FLAG_STARTCAPTURE | FLAG_CANCEL); + camera->cancel(); + camstate = CAMERA_IDLE; + infty = 0; // also cancel infinity loop + unlock(); + continue; + } camera_state curstate = camstate; switch(curstate){ case CAMERA_IDLE: @@ -603,7 +606,7 @@ static hresult expstatehandler(_U_ int fd, _U_ const char *key, _U_ const char * return RESULT_OK; } else if(n == CAMERA_CAPTURE){ // start exposition - TIMESTAMP("End of cycle - start new"); + TIMESTAMP("Get FLAG_STARTCAPTURE"); TIMEINIT(); camflags |= FLAG_STARTCAPTURE; return RESULT_OK; @@ -939,6 +942,18 @@ static hresult shmemkeyhandler(int fd, _U_ const char *key, _U_ const char *val) return RESULT_SILENCE; } +// infinity loop +static hresult inftyhandler(int fd, _U_ const char *key, const char *val){ + char buf[64]; + if(val){ + int i = atoi(val); + infty = (i) ? 1 : 0; + } + snprintf(buf, 63, CMD_INFTY "=%d", infty); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; + return RESULT_SILENCE; +} + // for setters: do nothing when camera not in idle state static int CAMbusy(){ if(camera && camstate != CAMERA_IDLE){ @@ -999,6 +1014,7 @@ static handleritem items[] = { {chkcc, _8bithandler, CMD_8BIT}, {chkcc, fastspdhandler, CMD_FASTSPD}, {chkcc, darkhandler, CMD_DARK}, + {chkcc, inftyhandler, CMD_INFTY}, {NULL, tremainhandler, CMD_TREMAIN}, {NULL, FITSparhandler, CMD_AUTHOR}, {NULL, FITSparhandler, CMD_INSTRUMENT}, @@ -1056,7 +1072,7 @@ void server(int sock, int imsock){ if(camera){ if(pthread_create(&camthread, NULL, processCAM, NULL)) ERR("pthread_create()"); } - int nfd = 2; // only one socket @start + int nfd = 2; // only two listening sockets @start: command and image struct pollfd poll_set[MAXCLIENTS+2]; char buffers[MAXCLIENTS][CLBUFSZ]; // buffers for data reading bzero(poll_set, sizeof(poll_set)); @@ -1105,7 +1121,10 @@ void server(int sock, int imsock){ } // process some data & send messages to ALL if(camstate == CAMERA_FRAMERDY || camstate == CAMERA_ERROR){ - if(camstate == CAMERA_FRAMERDY) ima->timestamp = dtime(); // set timestamp + if(camstate == CAMERA_FRAMERDY){ + ima->timestamp = dtime(); // set timestamp + ++ima->imnumber; // increment counter + } char buff[PATH_MAX+32]; snprintf(buff, PATH_MAX, CMD_EXPSTATE "=%d", camstate); DBG("Send %s to %d clients", buff, nfd - 2); @@ -1134,6 +1153,13 @@ void server(int sock, int imsock){ --nfd; } } + // check `infty` + if(camstate == CAMERA_IDLE && infty){ // start new exposition + // mark to start new capture in infinity loop when at least one client connected + if(nfd > 2) camflags |= FLAG_STARTCAPTURE; + TIMESTAMP("start new capture due to `infty`"); + TIMEINIT(); + } } focclose(focdev); closewheel(wheeldev); diff --git a/server.h b/server.h index a2ba9d9..b762a38 100644 --- a/server.h +++ b/server.h @@ -70,6 +70,7 @@ char *makeabspath(const char *path, int shouldbe); #define CMD_8BIT "8bit" #define CMD_FASTSPD "fastspeed" #define CMD_DARK "dark" +#define CMD_INFTY "infty" // FITS file keywords #define CMD_AUTHOR "author" #define CMD_INSTRUMENT "instrument" diff --git a/socket.h b/socket.h index 283935f..5d19c8c 100644 --- a/socket.h +++ b/socket.h @@ -36,7 +36,7 @@ // wait for mutex locking #define BUSY_TIMEOUT (1.0) // waiting for answer timeout -#define ANSWER_TIMEOUT (0.001) +#define ANSWER_TIMEOUT (0.01) // wait for exposition ends (between subsequent check calls) #define WAIT_TIMEOUT (2.0) // client will disconnect after this time from last server message