diff --git a/ZWO_cameras/zwofunc.c b/ZWO_cameras/zwofunc.c index e27d775..1493c2a 100644 --- a/ZWO_cameras/zwofunc.c +++ b/ZWO_cameras/zwofunc.c @@ -474,7 +474,7 @@ static void vstub(){ return; } static int istub(_U_ int N){ - return TRUE; + return FALSE; } /* diff --git a/ccdfunc.c b/ccdfunc.c index aebcff5..de448c7 100644 --- a/ccdfunc.c +++ b/ccdfunc.c @@ -146,8 +146,9 @@ static void addrec(fitsfile *f, char *filename){ } // save FITS file `img` into GP->outfile or GP->outfileprefix_XXXX.fits +// if outp != NULL, put into it strdup() of last file name // return FALSE if failed -int saveFITS(IMG *img){ +int saveFITS(IMG *img, char **outp){ int ret = FALSE; if(!camera){ LOGERR("Can't save image: no camera device"); @@ -224,8 +225,8 @@ int saveFITS(IMG *img){ WRITEKEY(fp, TSTRING, "GEOMETRY", bufc, "Camera current frame geometry"); // CRVAL1, CRVAL2 / Offset in X, Y if(GP->X0 > -1) WRITEKEY(fp, TINT, "X0", &GP->X0, "Subframe left border without binning"); if(GP->Y0 > -1) WRITEKEY(fp, TINT, "Y0", &GP->Y0, "Subframe upper border without binning"); - if(GP->objtype) strncpy(bufc, GP->objtype, FLEN_CARD-1); - else if(GP->dark) sprintf(bufc, "dark"); + if(GP->dark) sprintf(bufc, "dark"); + else if(GP->objtype) strncpy(bufc, GP->objtype, FLEN_CARD-1); else sprintf(bufc, "light"); // IMAGETYP / object, flat, dark, bias, scan, eta, neon, push WRITEKEY(fp, TSTRING, "IMAGETYP", bufc, "Image type"); @@ -327,11 +328,15 @@ int saveFITS(IMG *img){ TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, data); if(fitserror) goto cloerr; TRYFITS(fits_close_file, fp); - DBG("file %s saved", fnam); cloerr: if(fitserror == 0){ LOGMSG("Save file '%s'", fnam); verbose(1, _("File saved as '%s'"), fnam); + DBG("file %s saved", fnam); + if(outp){ + FREE(*outp); + *outp = strdup(fnam); + } ret = TRUE; }else{ LOGERR("Can't save %s", fnam); @@ -761,7 +766,7 @@ void ccds(){ break; } calculate_stat(&ima); - saveFITS(&ima); + saveFITS(&ima, NULL); #ifdef IMAGEVIEW if(GP->showimage){ // display image if((mainwin = getWin())){ diff --git a/ccdfunc.h b/ccdfunc.h index 1ad670a..b747cce 100644 --- a/ccdfunc.h +++ b/ccdfunc.h @@ -27,7 +27,7 @@ extern Focuser *focuser; extern Wheel *wheel; void calculate_stat(IMG *image); -int saveFITS(IMG *img); // for imageview module +int saveFITS(IMG *img, char **outp); // for imageview module void focusers(); void wheels(); void ccds(); diff --git a/client.c b/client.c index d6b2122..6d0092f 100644 --- a/client.c +++ b/client.c @@ -76,7 +76,13 @@ static char *getans(int sock){ buf[n] = 0; DBG("Got from server: %s", buf); verbose(1, "%s", buf); - if(buf[n-1] == '\n') break; + if(buf[n-1] == '\n'){ + buf[n-1] = 0; + break; + } + } + if(0 == strcmp(hresult2str(RESULT_BUSY), buf)){ + ERRX("Server busy"); } return ans; } @@ -108,16 +114,42 @@ static void process_data(int sock){ if(!isnan(GP->gain)) SENDMSG(CMD_GAIN "=%g", GP->gain); if(!isnan(GP->brightness)) SENDMSG(CMD_BRIGHTNESS "=%g", GP->brightness); if(GP->nflushes > 0) SENDMSG(CMD_NFLUSHES "=%d", GP->nflushes); - if(GP->outfile || GP->outfileprefix){ + if(GP->outfile || GP->outfileprefix){ // exposition and reading control: only if start of exposition + if(GP->_8bit) SENDMSG(CMD_8BIT "=1"); + else SENDMSG(CMD_8BIT "=0"); + if(GP->fast) SENDMSG(CMD_FASTSPD "=1"); + else SENDMSG(CMD_FASTSPD "=0"); + if(GP->dark) SENDMSG(CMD_DARK "=1"); + else SENDMSG(CMD_DARK "=0"); + } + if(GP->outfile){ + SENDMSG(CMD_FILENAME "=%s", makeabspath(GP->outfile, FALSE)); if(GP->rewrite) SENDMSG(CMD_REWRITE "=1"); else SENDMSG(CMD_REWRITE "=0"); } - if(GP->outfile) SENDMSG(CMD_FILENAME "=%s", makeabspath(GP->outfile)); - if(GP->outfileprefix) SENDMSG(CMD_FILENAMEPREFIX "=%s", makeabspath(GP->outfileprefix)); - // if client gives filename and exptime, make exposition - if(GP->exptime > -DBL_EPSILON){ - SENDMSG(CMD_EXPOSITION "=%g", GP->exptime); - if(GP->outfile || GP->outfileprefix) SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); + if(GP->outfileprefix) SENDMSG(CMD_FILENAMEPREFIX "=%s", makeabspath(GP->outfileprefix, FALSE)); + if(GP->exptime > -DBL_EPSILON) SENDMSG(CMD_EXPOSITION "=%g", GP->exptime); + // FITS header keywords: +#define CHKHDR(x, cmd) do{if(x) SENDMSG(cmd "=%s", x);}while(0) + CHKHDR(GP->author, CMD_AUTHOR); + CHKHDR(GP->instrument, CMD_INSTRUMENT); + CHKHDR(GP->observers, CMD_OBSERVER); + CHKHDR(GP->objname, CMD_OBJECT); + CHKHDR(GP->prog_id, CMD_PROGRAM); + CHKHDR(GP->objtype, CMD_OBJTYPE); +#undef CHKHDR + if(GP->addhdr){ + char buf[1024], *ptr = buf, **sptr = GP->addhdr; + *buf = 0; + int L = 1024; + while(*sptr){ + if(!**sptr){ + ++sptr; continue; + } + int N = snprintf(ptr, L-1, "%s,", *sptr++); + L -= N; ptr += N; + } + SENDMSG(CMD_HEADERFILES "=%s", buf); } // common information SENDMSG(CMD_INFO); @@ -125,14 +157,23 @@ static void process_data(int sock){ void client(int sock){ process_data(sock); - double timeout = GP->waitexpend ? CLIENT_TIMEOUT : 0.1; double t0 = dtime(), tw = t0; + int Nremain = 0, nframe = 1; + // if client gives filename/prefix or Nframes, make exposition + if(GP->outfile || GP->outfileprefix || GP->nframes > 0){ + Nremain = GP->nframes - 1; + if(Nremain < 1) Nremain = 0; + else GP->waitexpend = TRUE; // N>1 - wait for exp ends + SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); + } + double timeout = GP->waitexpend ? CLIENT_TIMEOUT : 0.1; + verbose(1, "Exposing frame 1"); + if(GP->waitexpend) verbose(2, "Wait for exposition end"); while(dtime() - t0 < timeout){ if(GP->waitexpend && dtime() - tw > WAIT_TIMEOUT){ SENDMSG(CMD_TREMAIN); // get remained time tw = dtime(); sprintf(sendbuf, "%s", CMD_EXPSTATE); - verbose(2, "%s", sendbuf); sendstrmessage(sock, sendbuf); } char *ans = getans(sock); @@ -147,7 +188,27 @@ void client(int sock){ } if(state != CAMERA_CAPTURE){ verbose(2, "Frame ready!"); - return; + SENDMSG(CMD_LASTFNAME); + if(Nremain){ + if(GP->pause_len > 0){ + double delta, time1 = dtime() + GP->pause_len; + while(1){ + SENDMSG(CMD_CAMTEMPER); + if((delta = time1 - dtime()) < __FLT_EPSILON__) break; + // %d ΣΕΛΥΞΔ ΔΟ ΟΛΟΞήΑΞΙΡ ΠΑΥΪΩ\n + if(delta > 1.) verbose(1, _("%d seconds till pause ends\n"), (int)delta); + if(delta > 6.) sleep(5); + else if(delta > 1.) sleep((int)delta); + else usleep((int)(delta*1e6 + 1)); + } + } + verbose(1, "Exposing frame %d", ++nframe); + --Nremain; + SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); + }else{ + GP->waitexpend = 0; + timeout = 0.2; // wait for last file name + } } } } diff --git a/cmdlnopts.c b/cmdlnopts.c index d0cc7be..3fc802e 100644 --- a/cmdlnopts.c +++ b/cmdlnopts.c @@ -89,7 +89,7 @@ myoption cmdlnopts[] = { {"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_double, APTR(&G.gotopos), N_("move focuser to absolute position, mm")}, - {"addsteps",NEED_ARG, NULL, 'a', arg_double, APTR(&G.addsteps), N_("move focuser to relative position, mm")}, + {"addsteps",NEED_ARG, NULL, 'a', arg_double, APTR(&G.addsteps), N_("move focuser to relative position, mm (only for standalone)")}, {"wheel-set",NEED_ARG, NULL, 'w', arg_int, APTR(&G.setwheel), N_("set wheel position")}, @@ -119,7 +119,7 @@ myoption cmdlnopts[] = { */ glob_pars *parse_args(int argc, char **argv){ // format of help: "Usage: progname [args]\n" - change_helpstring("Usage: %s [args] [output file prefix]\n\n\tWhere args are:\n"); + change_helpstring("Usage: %s [args] [output file prefix]\nTo restart server kill it with SIGUSR1\n\tArgs are:\n"); // parse arguments parseargs(&argc, &argv, cmdlnopts); if(help) showhelp(-1, cmdlnopts); diff --git a/imageview.c b/imageview.c index 06e6bd3..1309277 100644 --- a/imageview.c +++ b/imageview.c @@ -489,7 +489,7 @@ void* image_thread(_U_ void *data){ if(win && win->winevt){ if(win->winevt & WINEVT_SAVEIMAGE){ // save image verbose(2, "Make screenshot\n"); - saveFITS(img); + saveFITS(img, NULL); win->winevt &= ~WINEVT_SAVEIMAGE; } if(win->winevt & WINEVT_ROLLCOLORFUN){ diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 2d98da9..1150899 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: 2022-03-18 16:49+0300\n" +"POT-Creation-Date: 2022-03-21 18:20+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -202,7 +202,7 @@ msgid "move focuser to absolute position, mm" msgstr "" #: cmdlnopts.c:92 -msgid "move focuser to relative position, mm" +msgid "move focuser to relative position, mm (only for standalone)" msgstr "" #: cmdlnopts.c:94 @@ -261,16 +261,16 @@ msgstr "" msgid "Can't find wheel in plugin %s: %s" msgstr "" -#: ccdfunc.c:154 +#: ccdfunc.c:155 msgid "Camera device unknown" msgstr "" -#: ccdfunc.c:160 +#: ccdfunc.c:161 msgid "Neither filename nor filename prefix pointed!" msgstr "" #. НС ΠΌΠΎΠ³Ρƒ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Ρ„Π°ΠΉΠ» -#: ccdfunc.c:179 +#: ccdfunc.c:180 #, c-format msgid "Can't save file with prefix %s" msgstr "" @@ -280,281 +280,281 @@ msgstr "" msgid "File saved as '%s'" msgstr "" -#: ccdfunc.c:338 +#: ccdfunc.c:343 msgid "Error saving file" msgstr "" -#: ccdfunc.c:378 +#: ccdfunc.c:383 #, c-format msgid "Image stat:\n" msgstr "" -#: ccdfunc.c:386 +#: ccdfunc.c:391 msgid "Focuser device not pointed" msgstr "" -#: ccdfunc.c:393 +#: ccdfunc.c:398 msgid "No focusers found" msgstr "" -#: ccdfunc.c:424 +#: ccdfunc.c:429 #, c-format msgid "Found %d focusers, you point number %d" msgstr "" -#: ccdfunc.c:428 +#: ccdfunc.c:433 msgid "Can't set active focuser number" msgstr "" -#: ccdfunc.c:442 +#: ccdfunc.c:447 msgid "Can't get focuser limit positions" msgstr "" -#: ccdfunc.c:449 +#: ccdfunc.c:454 msgid "Can't get current focuser position" msgstr "" -#: ccdfunc.c:463 +#: ccdfunc.c:468 #, c-format msgid "Can't set position %g: out of limits [%g, %g]" msgstr "" -#: ccdfunc.c:467 +#: ccdfunc.c:472 msgid "Can't home focuser" msgstr "" -#: ccdfunc.c:469 +#: ccdfunc.c:474 #, c-format msgid "Can't set position %g" msgstr "" -#: ccdfunc.c:477 +#: ccdfunc.c:482 msgid "Wheel device not pointed" msgstr "" -#: ccdfunc.c:484 +#: ccdfunc.c:489 msgid "No wheels found" msgstr "" -#: ccdfunc.c:515 +#: ccdfunc.c:520 #, c-format msgid "Found %d wheels, you point number %d" msgstr "" -#: ccdfunc.c:519 +#: ccdfunc.c:524 msgid "Can't set active wheel number" msgstr "" -#: ccdfunc.c:535 +#: ccdfunc.c:540 msgid "Can't get max wheel position" msgstr "" -#: ccdfunc.c:542 +#: ccdfunc.c:547 #, c-format msgid "Wheel position should be from 0 to %d" msgstr "" -#: ccdfunc.c:546 +#: ccdfunc.c:551 #, c-format msgid "Can't set wheel position %d" msgstr "" -#: ccdfunc.c:563 +#: ccdfunc.c:568 #, c-format msgid "%.1f seconds till exposition ends" msgstr "" -#: ccdfunc.c:577 +#: ccdfunc.c:582 msgid "Camera device not pointed" msgstr "" -#: ccdfunc.c:584 ccdfunc.c:585 +#: ccdfunc.c:589 ccdfunc.c:590 msgid "No cameras found" msgstr "" -#: ccdfunc.c:620 +#: ccdfunc.c:625 #, c-format msgid "Found %d cameras, you point number %d" msgstr "" -#: ccdfunc.c:624 +#: ccdfunc.c:629 msgid "Can't set active camera number" msgstr "" -#: ccdfunc.c:630 +#: ccdfunc.c:635 msgid "Can't set fan speed" msgstr "" -#: ccdfunc.c:631 -#, c-format -msgid "Set fan speed to %d" -msgstr "" - #: ccdfunc.c:636 #, c-format +msgid "Set fan speed to %d" +msgstr "" + +#: ccdfunc.c:641 +#, c-format msgid "Camera model: %s" msgstr "" -#: ccdfunc.c:637 +#: ccdfunc.c:642 #, c-format msgid "Pixel size: %g x %g" msgstr "" -#: ccdfunc.c:643 +#: ccdfunc.c:648 #, c-format msgid "Full array: %s" msgstr "" -#: ccdfunc.c:646 +#: ccdfunc.c:651 #, c-format msgid "Field of view: %s" msgstr "" -#: ccdfunc.c:649 +#: ccdfunc.c:654 #, c-format msgid "Can't set T to %g degC" msgstr "" -#: ccdfunc.c:656 +#: ccdfunc.c:661 #, c-format msgid "Shutter command: %s\n" msgstr "" -#: ccdfunc.c:658 +#: ccdfunc.c:663 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr "" #. "ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° ΡΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΡ€Ρ‚ I/O ΠΊΠ°ΠΊ %d\n" -#: ccdfunc.c:662 +#: ccdfunc.c:667 #, c-format msgid "Try to configure I/O port as %d" msgstr "" -#: ccdfunc.c:664 +#: ccdfunc.c:669 msgid "Can't configure (unsupported?)" msgstr "" -#: ccdfunc.c:670 +#: ccdfunc.c:675 msgid "Can't get IOport state (unsupported?)" msgstr "" #. "ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° записи %d Π² ΠΏΠΎΡ€Ρ‚ I/O\n" -#: ccdfunc.c:674 +#: ccdfunc.c:679 #, c-format msgid "Try to write %d to I/O port" msgstr "" -#: ccdfunc.c:676 +#: ccdfunc.c:681 msgid "Can't set IOport" msgstr "" -#: ccdfunc.c:683 +#: ccdfunc.c:688 #, c-format msgid "Set gain to %g" msgstr "" -#: ccdfunc.c:684 +#: ccdfunc.c:689 #, c-format msgid "Can't set gain to %g" msgstr "" -#: ccdfunc.c:689 +#: ccdfunc.c:694 #, c-format msgid "Set brightness to %g" msgstr "" -#: ccdfunc.c:690 +#: ccdfunc.c:695 #, c-format msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:698 server.c:199 +#: ccdfunc.c:703 server.c:209 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:708 server.c:200 +#: ccdfunc.c:713 server.c:210 msgid "Can't set given geometry" msgstr "" -#: ccdfunc.c:712 +#: ccdfunc.c:717 #, c-format msgid "Can't set %d flushes" msgstr "" -#: ccdfunc.c:716 +#: ccdfunc.c:721 #, c-format msgid "Can't set exposure time to %f seconds" msgstr "" -#: ccdfunc.c:719 +#: ccdfunc.c:724 msgid "Can't change frame type" msgstr "" -#: ccdfunc.c:722 +#: ccdfunc.c:727 msgid "Can't set bit depth" msgstr "" -#: ccdfunc.c:724 +#: ccdfunc.c:729 msgid "Can't set readout speed" msgstr "" -#: ccdfunc.c:725 +#: ccdfunc.c:730 #, c-format msgid "Readout mode: %s" msgstr "" -#: ccdfunc.c:726 +#: ccdfunc.c:731 msgid "Only show statistics" msgstr "" #. GET binning should be AFTER setgeometry! -#: ccdfunc.c:728 +#: ccdfunc.c:733 msgid "Can't get current binning" msgstr "" -#: ccdfunc.c:741 +#: ccdfunc.c:746 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "" #. Π—Π°Ρ…Π²Π°Ρ‚ ΠΊΠ°Π΄Ρ€Π° %d\n -#: ccdfunc.c:748 +#: ccdfunc.c:753 #, c-format msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:750 server.c:108 +#: ccdfunc.c:755 server.c:118 msgid "Can't start exposition" msgstr "" -#: ccdfunc.c:754 ccdfunc.c:776 ccdfunc.c:817 +#: ccdfunc.c:759 ccdfunc.c:781 ccdfunc.c:822 msgid "Can't capture image" msgstr "" -#: ccdfunc.c:757 +#: ccdfunc.c:762 msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:760 ccdfunc.c:780 ccdfunc.c:821 +#: ccdfunc.c:765 ccdfunc.c:785 ccdfunc.c:826 msgid "Can't grab image" msgstr "" #. %d сСкунд Π΄ΠΎ окончания ΠΏΠ°ΡƒΠ·Ρ‹\n -#: ccdfunc.c:797 +#: ccdfunc.c:802 client.c:199 #, c-format msgid "%d seconds till pause ends\n" msgstr "" -#: server.c:146 +#: server.c:156 msgid "No camera device" msgstr "" -#: client.c:145 +#: client.c:186 msgid "Can't make exposition" msgstr "" -#: client.c:155 +#: client.c:216 msgid "Server timeout" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 0efda7c..99262b3 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: 2022-03-18 16:49+0300\n" + "POT-Creation-Date: 2022-03-21 18:20+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,13 +16,13 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n" "Content-Type: text/plain; charset=koi8-r\n" "Content-Transfer-Encoding: 8bit\n" -#: ccdfunc.c:563 +#: ccdfunc.c:568 #, c-format msgid "%.1f seconds till exposition ends" msgstr "" #. %d сСкунд Π΄ΠΎ окончания ΠΏΠ°ΡƒΠ·Ρ‹\n -#: ccdfunc.c:797 +#: ccdfunc.c:802 client.c:199 #, c-format msgid "%d seconds till pause ends\n" msgstr "" @@ -39,28 +39,28 @@ msgstr "" msgid "CMOS gain level" msgstr "" -#: ccdfunc.c:577 +#: ccdfunc.c:582 msgid "Camera device not pointed" msgstr "" -#: ccdfunc.c:154 +#: ccdfunc.c:155 msgid "Camera device unknown" msgstr "" -#: ccdfunc.c:636 +#: ccdfunc.c:641 #, c-format msgid "Camera model: %s" msgstr "" -#: ccdfunc.c:754 ccdfunc.c:776 ccdfunc.c:817 +#: ccdfunc.c:759 ccdfunc.c:781 ccdfunc.c:822 msgid "Can't capture image" msgstr "" -#: ccdfunc.c:719 +#: ccdfunc.c:724 msgid "Can't change frame type" msgstr "" -#: ccdfunc.c:664 +#: ccdfunc.c:669 msgid "Can't configure (unsupported?)" msgstr "" @@ -84,32 +84,32 @@ msgstr "" msgid "Can't find wheel in plugin %s: %s" msgstr "" -#: ccdfunc.c:670 +#: ccdfunc.c:675 msgid "Can't get IOport state (unsupported?)" msgstr "" #. GET binning should be AFTER setgeometry! -#: ccdfunc.c:728 +#: ccdfunc.c:733 msgid "Can't get current binning" msgstr "" -#: ccdfunc.c:449 +#: ccdfunc.c:454 msgid "Can't get current focuser position" msgstr "" -#: ccdfunc.c:442 +#: ccdfunc.c:447 msgid "Can't get focuser limit positions" msgstr "" -#: ccdfunc.c:535 +#: ccdfunc.c:540 msgid "Can't get max wheel position" msgstr "" -#: ccdfunc.c:760 ccdfunc.c:780 ccdfunc.c:821 +#: ccdfunc.c:765 ccdfunc.c:785 ccdfunc.c:826 msgid "Can't grab image" msgstr "" -#: ccdfunc.c:467 +#: ccdfunc.c:472 msgid "Can't home focuser" msgstr "" @@ -117,108 +117,108 @@ msgstr "" msgid "Can't init mutex!" msgstr "" -#: client.c:145 +#: client.c:186 msgid "Can't make exposition" msgstr "" -#: ccdfunc.c:741 +#: ccdfunc.c:746 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "" -#: ccdfunc.c:658 +#: ccdfunc.c:663 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr "" #. НС ΠΌΠΎΠ³Ρƒ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Ρ„Π°ΠΉΠ» -#: ccdfunc.c:179 +#: ccdfunc.c:180 #, c-format msgid "Can't save file with prefix %s" msgstr "" -#: ccdfunc.c:712 +#: ccdfunc.c:717 #, c-format msgid "Can't set %d flushes" msgstr "" -#: ccdfunc.c:676 +#: ccdfunc.c:681 msgid "Can't set IOport" msgstr "" -#: ccdfunc.c:649 +#: ccdfunc.c:654 #, c-format msgid "Can't set T to %g degC" msgstr "" -#: ccdfunc.c:624 +#: ccdfunc.c:629 msgid "Can't set active camera number" msgstr "" -#: ccdfunc.c:428 +#: ccdfunc.c:433 msgid "Can't set active focuser number" msgstr "" -#: ccdfunc.c:519 +#: ccdfunc.c:524 msgid "Can't set active wheel number" msgstr "" -#: ccdfunc.c:698 server.c:199 +#: ccdfunc.c:703 server.c:209 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:722 +#: ccdfunc.c:727 msgid "Can't set bit depth" msgstr "" -#: ccdfunc.c:690 +#: ccdfunc.c:695 #, c-format msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:716 +#: ccdfunc.c:721 #, c-format msgid "Can't set exposure time to %f seconds" msgstr "" -#: ccdfunc.c:630 +#: ccdfunc.c:635 msgid "Can't set fan speed" msgstr "" -#: ccdfunc.c:684 +#: ccdfunc.c:689 #, c-format msgid "Can't set gain to %g" msgstr "" -#: ccdfunc.c:708 server.c:200 +#: ccdfunc.c:713 server.c:210 msgid "Can't set given geometry" msgstr "" -#: ccdfunc.c:469 +#: ccdfunc.c:474 #, c-format msgid "Can't set position %g" msgstr "" -#: ccdfunc.c:463 +#: ccdfunc.c:468 #, c-format msgid "Can't set position %g: out of limits [%g, %g]" msgstr "" -#: ccdfunc.c:724 +#: ccdfunc.c:729 msgid "Can't set readout speed" msgstr "" -#: ccdfunc.c:546 +#: ccdfunc.c:551 #, c-format msgid "Can't set wheel position %d" msgstr "" -#: ccdfunc.c:750 server.c:108 +#: ccdfunc.c:755 server.c:118 msgid "Can't start exposition" msgstr "" #. Π—Π°Ρ…Π²Π°Ρ‚ ΠΊΠ°Π΄Ρ€Π° %d\n -#: ccdfunc.c:748 +#: ccdfunc.c:753 #, c-format msgid "Capture frame %d" msgstr "" @@ -232,11 +232,11 @@ msgstr "" msgid "Equalization of histogram: %s" msgstr "" -#: ccdfunc.c:338 +#: ccdfunc.c:343 msgid "Error saving file" msgstr "" -#: ccdfunc.c:646 +#: ccdfunc.c:651 #, c-format msgid "Field of view: %s" msgstr "" @@ -246,26 +246,26 @@ msgstr "" msgid "File saved as '%s'" msgstr "" -#: ccdfunc.c:386 +#: ccdfunc.c:391 msgid "Focuser device not pointed" msgstr "" -#: ccdfunc.c:620 +#: ccdfunc.c:625 #, c-format msgid "Found %d cameras, you point number %d" msgstr "" -#: ccdfunc.c:424 +#: ccdfunc.c:429 #, c-format msgid "Found %d focusers, you point number %d" msgstr "" -#: ccdfunc.c:515 +#: ccdfunc.c:520 #, c-format msgid "Found %d wheels, you point number %d" msgstr "" -#: ccdfunc.c:643 +#: ccdfunc.c:648 #, c-format msgid "Full array: %s" msgstr "" @@ -275,7 +275,7 @@ msgstr "" msgid "Histogram conversion: %s" msgstr "" -#: ccdfunc.c:378 +#: ccdfunc.c:383 #, c-format msgid "Image stat:\n" msgstr "" @@ -284,27 +284,27 @@ msgstr "" msgid "N flushes before exposing (default: 1)" msgstr "" -#: ccdfunc.c:160 +#: ccdfunc.c:161 msgid "Neither filename nor filename prefix pointed!" msgstr "" -#: server.c:146 +#: server.c:156 msgid "No camera device" msgstr "" -#: ccdfunc.c:584 ccdfunc.c:585 +#: ccdfunc.c:589 ccdfunc.c:590 msgid "No cameras found" msgstr "" -#: ccdfunc.c:393 +#: ccdfunc.c:398 msgid "No focusers found" msgstr "" -#: ccdfunc.c:484 +#: ccdfunc.c:489 msgid "No wheels found" msgstr "" -#: ccdfunc.c:726 +#: ccdfunc.c:731 msgid "Only show statistics" msgstr "" @@ -312,52 +312,52 @@ msgstr "" msgid "PID file (default: " msgstr "" -#: ccdfunc.c:637 +#: ccdfunc.c:642 #, c-format msgid "Pixel size: %g x %g" msgstr "" -#: ccdfunc.c:757 +#: ccdfunc.c:762 msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:725 +#: ccdfunc.c:730 #, c-format msgid "Readout mode: %s" msgstr "" -#: client.c:155 +#: client.c:216 msgid "Server timeout" msgstr "" -#: ccdfunc.c:689 +#: ccdfunc.c:694 #, c-format msgid "Set brightness to %g" msgstr "" -#: ccdfunc.c:631 +#: ccdfunc.c:636 #, c-format msgid "Set fan speed to %d" msgstr "" -#: ccdfunc.c:683 +#: ccdfunc.c:688 #, c-format msgid "Set gain to %g" msgstr "" -#: ccdfunc.c:656 +#: ccdfunc.c:661 #, c-format msgid "Shutter command: %s\n" msgstr "" #. "ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° ΡΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΡ€Ρ‚ I/O ΠΊΠ°ΠΊ %d\n" -#: ccdfunc.c:662 +#: ccdfunc.c:667 #, c-format msgid "Try to configure I/O port as %d" msgstr "" #. "ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° записи %d Π² ΠΏΠΎΡ€Ρ‚ I/O\n" -#: ccdfunc.c:674 +#: ccdfunc.c:679 #, c-format msgid "Try to write %d to I/O port" msgstr "" @@ -366,11 +366,11 @@ msgstr "" msgid "UNIX socket name" msgstr "" -#: ccdfunc.c:477 +#: ccdfunc.c:482 msgid "Wheel device not pointed" msgstr "" -#: ccdfunc.c:542 +#: ccdfunc.c:547 #, c-format msgid "Wheel position should be from 0 to %d" msgstr "" @@ -474,7 +474,7 @@ msgid "move focuser to absolute position, mm" msgstr "" #: cmdlnopts.c:92 -msgid "move focuser to relative position, mm" +msgid "move focuser to relative position, mm (only for standalone)" msgstr "" #: cmdlnopts.c:86 diff --git a/main.c b/main.c index 83d3768..89e0263 100644 --- a/main.c +++ b/main.c @@ -40,7 +40,13 @@ static int isserver = FALSE; static pid_t childpid = 0; void signals(int signo){ + signal(signo, SIG_IGN); if(childpid){ // master process + if(signo == SIGUSR1){ // kill child + kill(childpid, signo); + signal(signo, signals); + return; + } DBG("Master killed with sig=%d", signo); LOGWARN("Master killed with sig=%d", signo); if(!GP->client){ @@ -104,6 +110,7 @@ int main(int argc, char **argv){ signal(SIGTERM, signals); signal(SIGHUP, SIG_IGN); signal(SIGTSTP, SIG_IGN); + signal(SIGUSR1, signals); // restart server // check for another running process in server and standalone mode if(!GP->client) check4running(self, GP->pidfile); if(!isserver && !GP->client){ // standalone mode @@ -112,7 +119,6 @@ int main(int argc, char **argv){ ccds(); return 0; } - LOGMSG("Started"); #ifndef EBUG if(isserver){ diff --git a/server.c b/server.c index 6c6e820..6b090ed 100644 --- a/server.c +++ b/server.c @@ -35,7 +35,7 @@ static _Atomic camera_state camstate = CAMERA_IDLE; #define FLAG_STARTCAPTURE (1<<0) #define FLAG_CANCEL (1<<1) static atomic_int camflags = 0, camfanspd = 0, confio = 0, nflushes; -static char *outfile = NULL; +static char *outfile = NULL, *lastfile = NULL; // current output file name/prefix; last name of saved file static pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/focuser functions static frameformat frmformatmax = {0}, curformat = {0}; // maximal format static void *camdev = NULL, *focdev = NULL, *wheeldev = NULL; @@ -51,13 +51,17 @@ typedef struct{ // cat | awk '{print "{ " $3 ", \"\" }," }' | sort strpair allcommands[] = { + { "8bit", "run in 8 bit mode instead of 16 bit" }, + { "author", "FITS 'AUTHOR' field" }, { "brightness", "camera brightness" }, { "camdevno", "camera device number" }, { "camlist", "list all connected cameras" }, { "ccdfanspeed", "fan speed of camera" }, { "confio", "camera IO configuration" }, + { "dark", "don't open shutter @ exposure" }, { "expstate", "get exposition state" }, { "exptime", "exposition time" }, + { "fastspeed", "fast readout speed" }, { "filename", "save file with this name, like file.fits" }, { "filenameprefix", "prefix of files, like ex (will be saved as exXXXX.fits)" }, { "focdevno", "focuser device number" }, @@ -66,11 +70,17 @@ strpair allcommands[] = { { "format", "camera frame format (X0,Y0,X1,Y1)" }, { "gain", "camera gain" }, { "hbin", "horizontal binning" }, + { "headerfiles", "add FITS records from these files (comma-separated list)" }, { "help", "show this help" }, { "info", "connected devices state" }, + { "instrument", "FITS 'INSTRUME' field" }, { "io", "get/set camera IO" }, { "maxformat", "camera maximal available format" }, { "nflushes", "camera number of preflushes" }, + { "object", "FITS 'OBJECT' field" }, + { "objtype", "FITS 'IMAGETYP' field" }, + { "observer", "FITS 'OBSERVER' field" }, + { "program", "FITS 'PROG-ID' field" }, { "rewrite", "rewrite file (if give `filename`, not `filenameprefix`" }, { "shutter", "camera shutter's operations" }, { "tcold", "camera chip temperature" }, @@ -130,7 +140,7 @@ static inline void cameracapturestate(){ // capturing - wait for exposition ends if(!camera->capture(&ima)) LOGERR("Can't capture image"); else{ calculate_stat(&ima); - if(saveFITS(&ima)){ + if(saveFITS(&ima, &lastfile)){ camstate = CAMERA_FRAMERDY; return; } @@ -278,12 +288,21 @@ static hresult exphandler(int fd, _U_ const char *key, const char *val){ sendstrmessage(fd, buf); return RESULT_SILENCE; } +// show last filename of saved FITS +static hresult lastfnamehandler(int fd, _U_ const char *key, _U_ const char *val){ + char buf[PATH_MAX+1]; + pthread_mutex_lock(&locmutex); + snprintf(buf, PATH_MAX, CMD_LASTFNAME "=%s", lastfile); + sendstrmessage(fd, buf); + pthread_mutex_unlock(&locmutex); + return RESULT_SILENCE; +} // filename setter/getter static hresult namehandler(int fd, _U_ const char *key, const char *val){ char buf[PATH_MAX+1]; if(val){ pthread_mutex_lock(&locmutex); - char *path = makeabspath(val); + char *path = makeabspath(val, FALSE); if(!path){ LOGERR("Can't create file '%s'", val); pthread_mutex_unlock(&locmutex); @@ -305,7 +324,7 @@ static hresult nameprefixhandler(_U_ int fd, _U_ const char *key, const char *va char buf[PATH_MAX+1]; if(val){ pthread_mutex_lock(&locmutex); - char *path = makeabspath(val); + char *path = makeabspath(val, FALSE); if(!path){ LOGERR("Can't create file '%s'", val); pthread_mutex_unlock(&locmutex); @@ -567,6 +586,141 @@ static hresult tremainhandler(_U_ int fd, _U_ const char *key, _U_ const char *v sendstrmessage(fd, buf); return RESULT_SILENCE; } +static hresult _8bithandler(int fd, _U_ const char *key, const char *val){ + char buf[64]; + if(val){ + int s = atoi(val); + if(s != 0 && s != 1) return RESULT_BADVAL; + GP->_8bit = s; + s = !s; + if(!camera->setbitdepth(s)) return RESULT_FAIL; + } + snprintf(buf, 63, CMD_8BIT "=%d", GP->_8bit); + sendstrmessage(fd, buf); + return RESULT_SILENCE; +} +static hresult fastspdhandler(int fd, _U_ const char *key, const char *val){ + char buf[64]; + if(val){ + int b = atoi(val); + if(b != 0 && b != 1) return RESULT_BADVAL; + GP->fast = b; + if(!camera->setfastspeed(b)) return RESULT_FAIL; + } + snprintf(buf, 63, CMD_FASTSPD "=%d", GP->fast); + sendstrmessage(fd, buf); + return RESULT_SILENCE; +} +static hresult darkhandler(int fd, _U_ const char *key, const char *val){ + char buf[64]; + if(val){ + int d = atoi(val); + if(d != 0 && d != 1) return RESULT_BADVAL; + GP->dark = d; + d = !d; + if(!camera->setframetype(d)) return RESULT_FAIL; + } + snprintf(buf, 63, CMD_DARK "=%d", GP->dark); + sendstrmessage(fd, buf); + return RESULT_SILENCE; +} +static hresult FITSparhandler(int fd, const char *key, const char *val){ + char buf[256], **fitskey = NULL; + if(0 == strcmp(key, CMD_AUTHOR)){ + fitskey = &GP->author; + }else if(0 == strcmp(key, CMD_INSTRUMENT)){ + fitskey = &GP->instrument; + }else if(0 == strcmp(key, CMD_OBSERVER)){ + fitskey = &GP->observers; + }else if(0 == strcmp(key, CMD_OBJECT)){ + fitskey = &GP->objname; + }else if(0 == strcmp(key, CMD_PROGRAM)){ + fitskey = &GP->prog_id; + }else if(0 == strcmp(key, CMD_OBJTYPE)){ + fitskey = &GP->objtype; + }else return RESULT_BADKEY; + if(val){ + FREE(*fitskey); + *fitskey = strdup(val); + } + snprintf(buf, 255, "%s=%s", key, *fitskey); + sendstrmessage(fd, buf); + return RESULT_SILENCE; +} +static hresult FITSheaderhandler(int fd, _U_ const char *key, const char *val){ + char buf[BUFSIZ], **sptr; + static char *curhdr = NULL; + static int firstrun = 1; + if(val){ + int sz = 10, amount = 0; + pthread_mutex_lock(&locmutex); + // first we should check `val` + char b2[BUFSIZ], *bptr = buf; + snprintf(b2, BUFSIZ-1, "%s", val); + char **list = MALLOC(char*, sz), **lptr = list; + int L = BUFSIZ; + for(char *s = b2; ; s = NULL){ + char *tok = strtok(s, ",;"); + if(!tok){ + *lptr = NULL; + break; + } + // check path + char *newpath = makeabspath(tok, TRUE); + DBG("next token: %s, path: %s", tok, newpath); + if(!newpath){ // error! Free list and return err + DBG("No such file"); + sptr = list; + while(*sptr){ + FREE(*sptr++); + } + FREE(list); + pthread_mutex_unlock(&locmutex); + return RESULT_BADVAL; + } + *lptr++ = strdup(newpath); + if(++amount == sz){ + DBG("Realloc"); + sz += 10; + list = realloc(list, sz*sizeof(char*)); + bzero(&list[sz-10], 10*sizeof(char*)); + } + int N = snprintf(bptr, L-1, "%s,", newpath); + bptr += N; L -= N; + } + // free old list and change its value + if(GP->addhdr){ + DBG("Free old list"); + sptr = GP->addhdr; + while(*sptr){ + DBG("Free %s", *sptr); + free(*(sptr++)); + } + } + GP->addhdr = list; + FREE(curhdr); + if(*val && *val != ',') curhdr = strdup(buf); + DBG("curhdr now: %s", curhdr); + pthread_mutex_unlock(&locmutex); + } + if(!curhdr && firstrun){ + firstrun = 0; + if(GP->addhdr && *GP->addhdr){ + char *ptr = buf; + int L = BUFSIZ; + sptr = GP->addhdr; + while(*sptr){ + DBG("Add to curhdr: %s", *sptr); + int N = snprintf(ptr, L-1, "%s,", *sptr++); + L -= N; ptr += N; + } + curhdr = strdup(buf); + } + } + snprintf(buf, BUFSIZ-1, CMD_HEADERFILES "=%s", curhdr); + sendstrmessage(fd, buf); + return RESULT_SILENCE; +} /* static hresult handler(_U_ int fd, _U_ const char *key, _U_ const char *val){ char buf[64]; @@ -790,10 +944,21 @@ static handleritem items[] = { {chkcam, formathandler, CMD_FRAMEFORMAT}, {chkcam, formathandler, CMD_FRAMEMAX}, {chkcam, nflusheshandler, CMD_NFLUSHES}, - {chkcam, expstatehandler, CMD_EXPSTATE}, + {chktrue, expstatehandler, CMD_EXPSTATE}, {chkcam, nameprefixhandler, CMD_FILENAMEPREFIX}, {chkcam, rewritefilehandler, CMD_REWRITE}, + {chkcam, _8bithandler, CMD_8BIT}, + {chkcam, fastspdhandler, CMD_FASTSPD}, + {chkcam, darkhandler, CMD_DARK}, {chktrue, tremainhandler, CMD_TREMAIN}, + {chktrue, FITSparhandler, CMD_AUTHOR}, + {chktrue, FITSparhandler, CMD_INSTRUMENT}, + {chktrue, FITSparhandler, CMD_OBSERVER}, + {chktrue, FITSparhandler, CMD_OBJECT}, + {chktrue, FITSparhandler, CMD_PROGRAM}, + {chktrue, FITSparhandler, CMD_OBJTYPE}, + {chktrue, FITSheaderhandler, CMD_HEADERFILES}, + {chktrue, lastfnamehandler, CMD_LASTFNAME}, {chkfoc, foclisthandler, CMD_FOCLIST}, {chkfoc, fsetNhandler, CMD_FDEVNO}, {chkfoc, fgotohandler, CMD_FGOTO}, @@ -878,13 +1043,20 @@ void server(int sock){ closecam(camdev); } -char *makeabspath(const char *path){ +/** + * @brief makeabspath - convert path to absolute and check it + * @param path - path to file + * @param shoulbe - ==1 if file must exists + * @return abs path or NULL (if can't convert, can't create or file not exists) + */ +char *makeabspath(const char *path, int shouldbe){ static char buf[PATH_MAX+1]; if(!path) return NULL; char *ret = NULL; int unl = 0; FILE *f = fopen(path, "r"); if(!f){ + if(shouldbe) return NULL; f = fopen(path, "a"); if(!f){ WARN("Can't create %s", path); diff --git a/server.h b/server.h index 9175ad2..676fe52 100644 --- a/server.h +++ b/server.h @@ -32,7 +32,7 @@ typedef enum{ // server-side functions void server(int fd); -char *makeabspath(const char *path); +char *makeabspath(const char *path, int shouldbe); // common information about everything #define CMD_INFO "info" @@ -42,6 +42,7 @@ char *makeabspath(const char *path); #define CMD_CAMLIST "camlist" #define CMD_CAMDEVNO "camdevno" #define CMD_EXPOSITION "exptime" +#define CMD_LASTFNAME "lastfilename" #define CMD_FILENAME "filename" #define CMD_FILENAMEPREFIX "filenameprefix" // rewrite=1 will rewrite files, =0 - not (only for `filename`) @@ -61,6 +62,17 @@ char *makeabspath(const char *path); // expstate=CAMERA_CAPTURE will start exposition, CAMERA_IDLE - cancel #define CMD_EXPSTATE "expstate" #define CMD_TREMAIN "tremain" +#define CMD_8BIT "8bit" +#define CMD_FASTSPD "fastspeed" +#define CMD_DARK "dark" +// FITS file keywords +#define CMD_AUTHOR "author" +#define CMD_INSTRUMENT "instrument" +#define CMD_OBSERVER "observer" +#define CMD_OBJECT "object" +#define CMD_PROGRAM "program" +#define CMD_OBJTYPE "objtype" +#define CMD_HEADERFILES "headerfiles" // focuser #define CMD_FOCLIST "foclist"