From 644de638ca7ce1f2a1996658a848054229e482d5 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 28 Feb 2023 17:18:07 +0300 Subject: [PATCH] add network image transporting (pre-alpha yet: many bugs) --- GRH_cameras/grasshopper.c | 955 ++++++++++++++------------- basestructs.h | 4 - ccdfunc.c | 8 +- ccdfunc.h | 6 +- client.c | 126 +++- client.h | 10 +- cmdlnopts.h | 5 +- events.c | 7 +- events.h | 8 +- imageview.c | 2 + imageview.h | 6 +- locale/ru/LC_MESSAGES/ccd_capture.mo | Bin 11213 -> 11114 bytes locale/ru/messages.po | 146 ++-- locale/ru/ru.po | 149 +++-- main.c | 4 - omp.h | 3 - server.c | 59 +- server.h | 9 +- socket.c | 31 +- socket.h | 7 +- 20 files changed, 847 insertions(+), 698 deletions(-) diff --git a/GRH_cameras/grasshopper.c b/GRH_cameras/grasshopper.c index 8fb5248..153283f 100644 --- a/GRH_cameras/grasshopper.c +++ b/GRH_cameras/grasshopper.c @@ -1,476 +1,479 @@ -/* - * This file is part of the CCD_Capture project. - * Copyright 2023 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 -#include -#include - -#include "basestructs.h" -#include "omp.h" - -extern Camera camera; - -static fc2Context context; -static fc2PGRGuid guid; -static fc2Error err = FC2_ERROR_OK; - -static int isopened = FALSE, is16bit = FALSE; -static char camname[BUFSIZ] = {0}; - -#ifndef Stringify -#define Stringify(x) #x -#endif -#define FC2FN(fn, ...) do{err = FC2_ERROR_OK; if(FC2_ERROR_OK != (err=fn(context __VA_OPT__(,) __VA_ARGS__))){ \ - WARNX(Stringify(fn) "(): %s", fc2ErrorToDescription(err)); return FALSE;}}while(0) - -static void disconnect(){ - FNAME(); - if(!isopened) return; - fc2DestroyContext(context); - isopened = FALSE; -} - -static int getfloat(fc2PropertyType t, float *f){ - fc2Property prop = {0}; - prop.type = t; - FC2FN(fc2GetProperty, &prop); - if(!prop.present){ - DBG("No property %d", t); - return FALSE; - } - DBG("property %d: abs=%f, vala=%u, valb=%u", t, - prop.absValue, prop.valueA, prop.valueB); - if(f) *f = prop.absValue; - return TRUE; -} - -/** - * @brief setfloat - set absolute property value (float) - * @param t - type of property - * @param f - new value - * @return 1 if all OK - */ -static int setfloat(fc2PropertyType t, float f){ - fc2Property prop = {0}; - prop.type = t; - fc2PropertyInfo i = {0}; - i.type = t; - FC2FN(fc2GetProperty, &prop); - FC2FN(fc2GetPropertyInfo, &i); - if(!prop.present || !i.present) return 0; - if(prop.autoManualMode){ - if(!i.manualSupported){ - WARNX("Can't set auto-only property"); - return FALSE; - } - prop.autoManualMode = false; - } - if(!prop.absControl){ - if(!i.absValSupported){ - WARNX("Can't set non-absolute property to absolute value"); - return FALSE; - } - prop.absControl = true; - } - if(!prop.onOff){ - if(!i.onOffSupported){ - WARNX("Can't set property ON"); - return FALSE; - } - prop.onOff = true; - } - if(prop.onePush && i.onePushSupported) prop.onePush = false; - prop.valueA = prop.valueB = 0; - prop.absValue = f; - FC2FN(fc2SetProperty, &prop); - // now check - FC2FN(fc2GetProperty, &prop); - if(fabsf(prop.absValue - f) > 0.02f){ - WARNX("Can't set property! Got %g instead of %g.", prop.absValue, f); - return FALSE; - } - return TRUE; -} - -static int propOnOff(fc2PropertyType t, BOOL onOff){ - fc2Property prop = {0}; - prop.type = t; - fc2PropertyInfo i = {0}; - i.type = t; - FC2FN(fc2GetPropertyInfo, &i); - FC2FN(fc2GetProperty, &prop); - if(!prop.present || !i.present) return 0; - if(prop.onOff == onOff) return 0; - if(!i.onOffSupported){ - WARNX("Property doesn't support state OFF"); - return 0; - } - prop.onOff = onOff; - FC2FN(fc2SetProperty, &prop); - FC2FN(fc2GetProperty, &prop); - if(prop.onOff != onOff){ - WARNX("Can't change property OnOff state"); - return 0; - } - return 1; -} - -static void disableauto(){ - if(!isopened) return; - propOnOff(FC2_AUTO_EXPOSURE, false); - propOnOff(FC2_WHITE_BALANCE, false); - propOnOff(FC2_GAMMA, false); - propOnOff(FC2_TRIGGER_MODE, false); - propOnOff(FC2_TRIGGER_DELAY, false); - propOnOff(FC2_FRAME_RATE, false); -} - -static int connect(){ - FNAME(); - unsigned int numDevices; - disconnect(); - DBG("fc2CreateContext"); - if(FC2_ERROR_OK != (err = fc2CreateContext(&context))){ - WARNX("fc2CreateContext(): %s", fc2ErrorToDescription(err)); - return FALSE; - } - DBG("fc2GetNumOfCameras"); - FC2FN(fc2GetNumOfCameras, &numDevices); - DBG("test"); - if(numDevices == 0){ - WARNX("No cameras detected!"); - fc2DestroyContext(context); - return FALSE; - } - camera.Ndevices = numDevices; - DBG("Found %d camera[s]", numDevices); - return TRUE; -} - -static int getbin(int *binh, int *binv){ - //unsigned int h, v; - //FC2FN(fc2GetGigEImageBinningSettings, &h, &v); - //green("got: %u x %u", h, v); - if(binh) *binh = 1; - if(binv) *binv = 1; - return TRUE; -} - -static int getformat(frameformat *fmt){ - if(!fmt) return FALSE; - unsigned int packsz; float pc; - fc2Format7ImageSettings f7; - FC2FN(fc2GetFormat7Configuration, &f7, &packsz, &pc); - fmt->h = f7.height; fmt->w = f7.width; - fmt->xoff = f7.offsetX; fmt->yoff = f7.offsetY; - if(f7.pixelFormat != FC2_PIXEL_FORMAT_MONO16){ - is16bit = FALSE; - DBG("8 bit"); - }else{ - is16bit = TRUE; - DBG("16 bit"); - } - return TRUE; -} - -static int getgeom(){ - FNAME(); - if(!isopened) return FALSE; - fc2Format7Info f = {.mode = FC2_MODE_0}; - BOOL b; - FC2FN(fc2GetFormat7Info, &f, &b); - - if(!b) return FALSE; - camera.array.h = f.maxHeight; - camera.array.w = f.maxWidth; - camera.array.xoff = camera.array.yoff = 0; - camera.field = camera.array; - getformat(&camera.geometry); - return TRUE; -} - -static int geometrylimits(frameformat *max, frameformat *step){ - FNAME(); - if(!isopened || !max || !step) return FALSE; - fc2Format7Info f = {.mode = FC2_MODE_0}; - BOOL b; - fc2Format7Info i = {0}; - FC2FN(fc2GetFormat7Info, &i, &b); - if(!b) return FALSE; - max->h = f.maxHeight; max->w = f.maxWidth; - max->xoff = f.maxWidth - f.offsetHStepSize; - max->yoff = f.maxHeight - f.offsetVStepSize; - step->w = f.imageHStepSize; - step->h = f.imageVStepSize; - step->xoff = f.offsetHStepSize; - step->yoff = f.offsetVStepSize; - return TRUE; -} - -static int setdevno(int N){ - if(N > camera.Ndevices - 1) return FALSE; - FC2FN(fc2GetCameraFromIndex, 0, &guid); - FC2FN(fc2Connect, &guid); - isopened = TRUE; - disableauto(); - fc2CameraInfo caminfo; - FC2FN(fc2GetCameraInfo, &caminfo); - if(err == FC2_ERROR_OK){ - strncpy(camname, caminfo.modelName, BUFSIZ-1); - DBG("Using camera %s\n", camname); - }else strcpy(camname, "Unknown camera"); - - if(!getbin(NULL, NULL)) WARNX("Can't get current binning"); - if(!getgeom()) WARNX("Can't get current frame format"); - return TRUE; -} - -// stub function: the capture process is blocking -static int pollcapt(capture_status *st, float *remain){ - if(st) *st = CAPTURE_READY; - if(remain) *remain = 0.f; - return TRUE; -} - -static int GrabImage(fc2Image *convertedImage){ - if(!convertedImage) return FALSE; - int ret = FALSE; - fc2Image rawImage; - // start capture - FC2FN(fc2StartCapture); - err = fc2CreateImage(&rawImage); - if(err != FC2_ERROR_OK){ - WARNX("Error in fc2CreateImage: %s", fc2ErrorToDescription(err)); - fc2StopCapture(context); - return FALSE; - } - // Retrieve the image - err = fc2RetrieveBuffer(context, &rawImage); - if(err != FC2_ERROR_OK){ - WARNX("Error in fc2RetrieveBuffer: %s", fc2ErrorToDescription(err)); - goto rtn; - } - // Convert image to gray (we need to convert RAW into same bitpix - fc2PixelFormat fmt = (is16bit) ? FC2_PIXEL_FORMAT_MONO16 : FC2_PIXEL_FORMAT_MONO8; - err = fc2ConvertImageTo(fmt, &rawImage, convertedImage); - if(err != FC2_ERROR_OK){ - WARNX("Error in fc2ConvertImageTo: %s", fc2ErrorToDescription(err)); - goto rtn; - } - ret = TRUE; - DBG("raw: ds=%u, rds=%u, str=%u; conv: ds=%u, rds=%u, str=%u", rawImage.dataSize, rawImage.receivedDataSize, rawImage.stride, - convertedImage->dataSize, convertedImage->receivedDataSize, convertedImage->stride); -rtn: - fc2StopCapture(context); - fc2DestroyImage(&rawImage); - return ret; -} - -static int capture(IMG *ima){ - FNAME(); - if(!ima || !ima->data || !isopened) return FALSE; - static int toohot = FALSE; - float f; - if(getfloat(FC2_TEMPERATURE, &f)){ - DBG("Temperature: %.1f", f); - if(f > 80.){ - WARNX("Device is too hot"); - toohot = TRUE; - }else if(toohot && f < 75.){ - DBG("Device temperature is normal"); - toohot = FALSE; - } - } - - fc2Image convertedImage; - err = fc2CreateImage(&convertedImage); - if(err != FC2_ERROR_OK){ - WARNX("capture_grasshopper(): can't create image, %s", fc2ErrorToDescription(err)); - return FALSE; - } - if(!GrabImage(&convertedImage)){ - WARNX("Can't grab image"); - fc2DestroyImage(&convertedImage); - return FALSE; - } - int width = convertedImage.cols, height = convertedImage.rows, stride = convertedImage.stride; - DBG("w=%d, h=%d, s=%d", width, height, stride); - if(is16bit){ - int w2 = width<<1; - OMP_FOR() - for(int y = 0; y < height; ++y){ - uint16_t *Out = &ima->data[y*width]; - const uint8_t *In = &convertedImage.pData[y*stride]; - memcpy(Out, In, w2); - } - }else{ - OMP_FOR() - for(int y = 0; y < height; ++y){ - uint16_t *Out = &ima->data[y*width]; - const uint8_t *In = &convertedImage.pData[y*stride]; - for(int x = 0; x < width; ++x){ - *Out++ = *In++; - } - } - } - ima->bitpix = is16bit ? 16 : 8; - fc2DestroyImage(&convertedImage); - return TRUE; -} - -static int setbrightness(float b){ - return setfloat(FC2_BRIGHTNESS, b); -} - -static int setexp(float e){ - FNAME(); - if(!isopened) return FALSE; - e *= 1e3f; - if(!setfloat(FC2_SHUTTER, e)){ - WARNX("Can't set expose time %g", e); - return FALSE; - } - return TRUE; -} - -static int setgain(float e){ - FNAME(); - if(!isopened) return FALSE; - if(!setfloat(FC2_GAIN, e)){ - WARNX("Can't set gain %g", e); - return FALSE; - } - DBG("GAIN -> %f", e); - return TRUE; -} - -static int changeformat(frameformat *fmt){ - FNAME(); - if(!isopened) return FALSE; - DBG("set geom %dx%d (off: %dx%d)", fmt->w, fmt->h, fmt->xoff, fmt->yoff); - BOOL b; - fc2Format7ImageSettings f7; - f7.mode = FC2_MODE_0; - f7.offsetX = fmt->xoff; - f7.offsetY = fmt->yoff; - f7.width = fmt->w; - f7.height = fmt->h; - DBG("offx=%d, offy=%d, w=%d, h=%d ", f7.offsetX, f7.offsetY, f7.width, f7.height); - f7.pixelFormat = (is16bit) ? FC2_PIXEL_FORMAT_MONO16 : FC2_PIXEL_FORMAT_MONO8; - fc2Format7PacketInfo f7p; - FC2FN(fc2ValidateFormat7Settings, &f7, &b, &f7p); - if(!b) return FALSE; // invalid - FC2FN(fc2SetFormat7Configuration, &f7, f7p.recommendedBytesPerPacket); - getformat(&camera.geometry); - return TRUE; -} - -static int setbitdepth(int i){ - frameformat fmt; - getformat(&fmt); - int o16bit = is16bit; - if(i == 0) is16bit = FALSE; // 8 bit - else is16bit = TRUE; - if(!changeformat(&fmt)){ - is16bit = o16bit; - return FALSE; - } - return TRUE; -} - -static int getgain(float *g){ - return getfloat(FC2_GAIN, g); -} - -static int gainmax(float *g){ - if(g) *g = 32.f; - return TRUE; -} - -static int modelname(char *buf, int bufsz){ - strncpy(buf, camname, bufsz); - return TRUE; -} - -// can't do binning -static int setbin(int binh, int binv){ - //FC2FN(fc2SetGigEImageBinningSettings, binh, binv); - //getbin(&binh, &binv); - if(binh != 1 || binv != 1) return FALSE; - return TRUE; -} - -static int gett(float *t){ - return getfloat(FC2_TEMPERATURE, t); -} - -static int setfanspd(_U_ fan_speed s){ - return FALSE; -} -static int shutter(_U_ shutter_op cmd){ - return FALSE; -} - -static int ffalse(_U_ float f){ return FALSE; } -static int fpfalse(_U_ float *f){ return FALSE; } -static int ifalse(_U_ int i){ return FALSE; } -static int vtrue(){ return TRUE; } -static int ipfalse(_U_ int *i){ return FALSE; } -static void vstub(){ return ;} - -/* - * Global objects: camera, focuser and wheel - */ -Camera camera = { - .check = connect, - .close = disconnect, - .pollcapture = pollcapt, - .capture = capture, - .cancel = vstub, - .startexposition = vtrue, - // setters: - .setDevNo = setdevno, - .setbrightness = setbrightness, - .setexp = setexp, - .setgain = setgain, - .setT = ffalse, - .setbin = setbin, - .setnflushes = ifalse, - .shuttercmd = shutter, - .confio = ifalse, - .setio = ifalse, - .setframetype = ifalse, // set DARK or NORMAL: no shutter -> no darks - .setbitdepth = setbitdepth, - .setfastspeed = ifalse, - .setgeometry = changeformat, - .setfanspeed = setfanspd, - // getters: - .getbrightness = fpfalse, - .getModelName = modelname, - .getgain = getgain, - .getmaxgain = gainmax, - .getgeomlimits = geometrylimits, - .getTcold = fpfalse, - .getThot = fpfalse, - .getTbody = gett, - .getbin = getbin, - .getio = ipfalse, -}; +/* + * This file is part of the CCD_Capture project. + * Copyright 2023 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 +#include +#include + +#include "basestructs.h" +#include "omp.h" + +extern Camera camera; + +static fc2Context context; +static fc2PGRGuid guid; +static fc2Error err = FC2_ERROR_OK; + +static int isopened = FALSE, is16bit = FALSE; +static char camname[BUFSIZ] = {0}; + +#ifndef Stringify +#define Stringify(x) #x +#endif +#define FC2FN(fn, ...) do{err = FC2_ERROR_OK; if(FC2_ERROR_OK != (err=fn(context __VA_OPT__(,) __VA_ARGS__))){ \ + WARNX(Stringify(fn) "(): %s", fc2ErrorToDescription(err)); return FALSE;}}while(0) + +static void disconnect(){ + FNAME(); + if(!isopened) return; + fc2DestroyContext(context); + isopened = FALSE; +} + +static int getfloat(fc2PropertyType t, float *f){ + fc2Property prop = {0}; + prop.type = t; + FC2FN(fc2GetProperty, &prop); + if(!prop.present){ + DBG("No property %d", t); + return FALSE; + } + DBG("property %d: abs=%f, vala=%u, valb=%u", t, + prop.absValue, prop.valueA, prop.valueB); + if(f) *f = prop.absValue; + return TRUE; +} + +/** + * @brief setfloat - set absolute property value (float) + * @param t - type of property + * @param f - new value + * @return 1 if all OK + */ +static int setfloat(fc2PropertyType t, float f){ + fc2Property prop = {0}; + prop.type = t; + fc2PropertyInfo i = {0}; + i.type = t; + FC2FN(fc2GetProperty, &prop); + FC2FN(fc2GetPropertyInfo, &i); + if(!prop.present || !i.present) return 0; + if(prop.autoManualMode){ + if(!i.manualSupported){ + WARNX("Can't set auto-only property"); + return FALSE; + } + prop.autoManualMode = false; + } + if(!prop.absControl){ + if(!i.absValSupported){ + WARNX("Can't set non-absolute property to absolute value"); + return FALSE; + } + prop.absControl = true; + } + if(!prop.onOff){ + if(!i.onOffSupported){ + WARNX("Can't set property ON"); + return FALSE; + } + prop.onOff = true; + } + if(prop.onePush && i.onePushSupported) prop.onePush = false; + prop.valueA = prop.valueB = 0; + prop.absValue = f; + FC2FN(fc2SetProperty, &prop); + // now check + FC2FN(fc2GetProperty, &prop); + if(fabsf(prop.absValue - f) > 0.02f){ + WARNX("Can't set property! Got %g instead of %g.", prop.absValue, f); + return FALSE; + } + return TRUE; +} + +static int propOnOff(fc2PropertyType t, BOOL onOff){ + fc2Property prop = {0}; + prop.type = t; + fc2PropertyInfo i = {0}; + i.type = t; + FC2FN(fc2GetPropertyInfo, &i); + FC2FN(fc2GetProperty, &prop); + if(!prop.present || !i.present) return 0; + if(prop.onOff == onOff) return 0; + if(!i.onOffSupported){ + WARNX("Property doesn't support state OFF"); + return 0; + } + prop.onOff = onOff; + FC2FN(fc2SetProperty, &prop); + FC2FN(fc2GetProperty, &prop); + if(prop.onOff != onOff){ + WARNX("Can't change property OnOff state"); + return 0; + } + return 1; +} + +static void disableauto(){ + if(!isopened) return; + propOnOff(FC2_AUTO_EXPOSURE, false); + propOnOff(FC2_WHITE_BALANCE, false); + propOnOff(FC2_GAMMA, false); + propOnOff(FC2_TRIGGER_MODE, false); + propOnOff(FC2_TRIGGER_DELAY, false); + propOnOff(FC2_FRAME_RATE, false); +} + +static int connect(){ + FNAME(); + unsigned int numDevices; + disconnect(); + DBG("fc2CreateContext"); + if(FC2_ERROR_OK != (err = fc2CreateContext(&context))){ + WARNX("fc2CreateContext(): %s", fc2ErrorToDescription(err)); + return FALSE; + } + DBG("fc2GetNumOfCameras"); + FC2FN(fc2GetNumOfCameras, &numDevices); + DBG("test"); + if(numDevices == 0){ + WARNX("No cameras detected!"); + fc2DestroyContext(context); + return FALSE; + } + camera.Ndevices = numDevices; + DBG("Found %d camera[s]", numDevices); + return TRUE; +} + +static int getbin(int *binh, int *binv){ + //unsigned int h, v; + //FC2FN(fc2GetGigEImageBinningSettings, &h, &v); + //green("got: %u x %u", h, v); + if(binh) *binh = 1; + if(binv) *binv = 1; + return TRUE; +} + +static int getformat(frameformat *fmt){ + if(!fmt) return FALSE; + unsigned int packsz; float pc; + fc2Format7ImageSettings f7; + FC2FN(fc2GetFormat7Configuration, &f7, &packsz, &pc); + fmt->h = f7.height; fmt->w = f7.width; + fmt->xoff = f7.offsetX; fmt->yoff = f7.offsetY; + if(f7.pixelFormat != FC2_PIXEL_FORMAT_MONO16){ + is16bit = FALSE; + DBG("8 bit"); + }else{ + is16bit = TRUE; + DBG("16 bit"); + } + return TRUE; +} + +static int getgeom(){ + FNAME(); + if(!isopened) return FALSE; + fc2Format7Info f = {.mode = FC2_MODE_0}; + BOOL b; + FC2FN(fc2GetFormat7Info, &f, &b); + + if(!b) return FALSE; + camera.array.h = f.maxHeight; + camera.array.w = f.maxWidth; + camera.array.xoff = camera.array.yoff = 0; + camera.field = camera.array; + getformat(&camera.geometry); + return TRUE; +} + +static int geometrylimits(frameformat *max, frameformat *step){ + FNAME(); + if(!isopened || !max || !step) return FALSE; + fc2Format7Info f = {.mode = FC2_MODE_0}; + BOOL b; + //fc2Format7Info i = {0}; + FC2FN(fc2GetFormat7Info, &f, &b); + if(!b) return FALSE; + max->h = f.maxHeight; max->w = f.maxWidth; + max->xoff = f.maxWidth - f.offsetHStepSize; + max->yoff = f.maxHeight - f.offsetVStepSize; + step->w = f.imageHStepSize; + step->h = f.imageVStepSize; + step->xoff = f.offsetHStepSize; + step->yoff = f.offsetVStepSize; + DBG("Got max w/h: %d/%d", f.maxWidth, f.maxHeight); + return TRUE; +} + +static int setdevno(int N){ + if(N > camera.Ndevices - 1) return FALSE; + FC2FN(fc2GetCameraFromIndex, 0, &guid); + FC2FN(fc2Connect, &guid); + isopened = TRUE; + disableauto(); + fc2CameraInfo caminfo; + FC2FN(fc2GetCameraInfo, &caminfo); + if(err == FC2_ERROR_OK){ + strncpy(camname, caminfo.modelName, BUFSIZ-1); + DBG("Using camera %s\n", camname); + }else strcpy(camname, "Unknown camera"); + + if(!getbin(NULL, NULL)) WARNX("Can't get current binning"); + if(!getgeom()) WARNX("Can't get current frame format"); + return TRUE; +} + +// stub function: the capture process is blocking +static int pollcapt(capture_status *st, float *remain){ + if(st) *st = CAPTURE_READY; + if(remain) *remain = 0.f; + return TRUE; +} + +static int GrabImage(fc2Image *convertedImage){ + if(!convertedImage) return FALSE; + int ret = FALSE; + fc2Image rawImage; + // start capture + FC2FN(fc2StartCapture); + err = fc2CreateImage(&rawImage); + if(err != FC2_ERROR_OK){ + WARNX("Error in fc2CreateImage: %s", fc2ErrorToDescription(err)); + fc2StopCapture(context); + return FALSE; + } + // Retrieve the image + err = fc2RetrieveBuffer(context, &rawImage); + if(err != FC2_ERROR_OK){ + WARNX("Error in fc2RetrieveBuffer: %s", fc2ErrorToDescription(err)); + goto rtn; + } + // Convert image to gray (we need to convert RAW into same bitpix + fc2PixelFormat fmt = (is16bit) ? FC2_PIXEL_FORMAT_MONO16 : FC2_PIXEL_FORMAT_MONO8; + err = fc2ConvertImageTo(fmt, &rawImage, convertedImage); + if(err != FC2_ERROR_OK){ + WARNX("Error in fc2ConvertImageTo: %s", fc2ErrorToDescription(err)); + goto rtn; + } + ret = TRUE; + DBG("raw: ds=%u, rds=%u, str=%u; conv: ds=%u, rds=%u, str=%u", rawImage.dataSize, rawImage.receivedDataSize, rawImage.stride, + convertedImage->dataSize, convertedImage->receivedDataSize, convertedImage->stride); +rtn: + fc2StopCapture(context); + fc2DestroyImage(&rawImage); + return ret; +} + +static int capture(IMG *ima){ + FNAME(); + if(!ima || !ima->data || !isopened) return FALSE; + static int toohot = FALSE; + float f; + if(getfloat(FC2_TEMPERATURE, &f)){ + DBG("Temperature: %.1f", f); + if(f > 80.){ + WARNX("Device is too hot"); + toohot = TRUE; + }else if(toohot && f < 75.){ + DBG("Device temperature is normal"); + toohot = FALSE; + } + } + + fc2Image convertedImage; + err = fc2CreateImage(&convertedImage); + if(err != FC2_ERROR_OK){ + WARNX("capture_grasshopper(): can't create image, %s", fc2ErrorToDescription(err)); + return FALSE; + } + if(!GrabImage(&convertedImage)){ + WARNX("Can't grab image"); + fc2DestroyImage(&convertedImage); + return FALSE; + } + int width = convertedImage.cols, height = convertedImage.rows, stride = convertedImage.stride; + DBG("w=%d, h=%d, s=%d", width, height, stride); + if(is16bit){ + int w2 = width<<1; + OMP_FOR() + for(int y = 0; y < height; ++y){ + uint16_t *Out = &ima->data[y*width]; + const uint8_t *In = &convertedImage.pData[y*stride]; + memcpy(Out, In, w2); + //DBG("Row %d copied. First byte: %d", y, *((uint16_t*)In)); + } + }else{ + OMP_FOR() + for(int y = 0; y < height; ++y){ + uint16_t *Out = &ima->data[y*width]; + const uint8_t *In = &convertedImage.pData[y*stride]; + for(int x = 0; x < width; ++x){ + *Out++ = *In++; + } + //DBG("Row %d copied. Last byte: %d", y, *((uint16_t*)In)); + } + } + ima->bitpix = is16bit ? 16 : 8; + fc2DestroyImage(&convertedImage); + return TRUE; +} + +static int setbrightness(float b){ + return setfloat(FC2_BRIGHTNESS, b); +} + +static int setexp(float e){ + FNAME(); + if(!isopened) return FALSE; + e *= 1e3f; + if(!setfloat(FC2_SHUTTER, e)){ + WARNX("Can't set expose time %g", e); + return FALSE; + } + return TRUE; +} + +static int setgain(float e){ + FNAME(); + if(!isopened) return FALSE; + if(!setfloat(FC2_GAIN, e)){ + WARNX("Can't set gain %g", e); + return FALSE; + } + DBG("GAIN -> %f", e); + return TRUE; +} + +static int changeformat(frameformat *fmt){ + FNAME(); + if(!isopened) return FALSE; + DBG("set geom %dx%d (off: %dx%d)", fmt->w, fmt->h, fmt->xoff, fmt->yoff); + BOOL b; + fc2Format7ImageSettings f7; + f7.mode = FC2_MODE_0; + f7.offsetX = fmt->xoff; + f7.offsetY = fmt->yoff; + f7.width = fmt->w; + f7.height = fmt->h; + DBG("offx=%d, offy=%d, w=%d, h=%d ", f7.offsetX, f7.offsetY, f7.width, f7.height); + f7.pixelFormat = (is16bit) ? FC2_PIXEL_FORMAT_MONO16 : FC2_PIXEL_FORMAT_MONO8; + fc2Format7PacketInfo f7p; + FC2FN(fc2ValidateFormat7Settings, &f7, &b, &f7p); + if(!b) return FALSE; // invalid + FC2FN(fc2SetFormat7Configuration, &f7, f7p.recommendedBytesPerPacket); + getformat(&camera.geometry); + return TRUE; +} + +static int setbitdepth(int i){ + frameformat fmt; + getformat(&fmt); + int o16bit = is16bit; + if(i == 0) is16bit = FALSE; // 8 bit + else is16bit = TRUE; + if(!changeformat(&fmt)){ + is16bit = o16bit; + return FALSE; + } + return TRUE; +} + +static int getgain(float *g){ + return getfloat(FC2_GAIN, g); +} + +static int gainmax(float *g){ + if(g) *g = 32.f; + return TRUE; +} + +static int modelname(char *buf, int bufsz){ + strncpy(buf, camname, bufsz); + return TRUE; +} + +// can't do binning +static int setbin(int binh, int binv){ + //FC2FN(fc2SetGigEImageBinningSettings, binh, binv); + //getbin(&binh, &binv); + if(binh != 1 || binv != 1) return FALSE; + return TRUE; +} + +static int gett(float *t){ + return getfloat(FC2_TEMPERATURE, t); +} + +static int setfanspd(_U_ fan_speed s){ + return FALSE; +} +static int shutter(_U_ shutter_op cmd){ + return FALSE; +} + +static int ffalse(_U_ float f){ return FALSE; } +static int fpfalse(_U_ float *f){ return FALSE; } +static int ifalse(_U_ int i){ return FALSE; } +static int vtrue(){ return TRUE; } +static int ipfalse(_U_ int *i){ return FALSE; } +static void vstub(){ return ;} + +/* + * Global objects: camera, focuser and wheel + */ +Camera camera = { + .check = connect, + .close = disconnect, + .pollcapture = pollcapt, + .capture = capture, + .cancel = vstub, + .startexposition = vtrue, + // setters: + .setDevNo = setdevno, + .setbrightness = setbrightness, + .setexp = setexp, + .setgain = setgain, + .setT = ffalse, + .setbin = setbin, + .setnflushes = ifalse, + .shuttercmd = shutter, + .confio = ifalse, + .setio = ifalse, + .setframetype = ifalse, // set DARK or NORMAL: no shutter -> no darks + .setbitdepth = setbitdepth, + .setfastspeed = ifalse, + .setgeometry = changeformat, + .setfanspeed = setfanspd, + // getters: + .getbrightness = fpfalse, + .getModelName = modelname, + .getgain = getgain, + .getmaxgain = gainmax, + .getgeomlimits = geometrylimits, + .getTcold = fpfalse, + .getThot = fpfalse, + .getTbody = gett, + .getbin = getbin, + .getio = ipfalse, +}; diff --git a/basestructs.h b/basestructs.h index ea8b633..d9a6d76 100644 --- a/basestructs.h +++ b/basestructs.h @@ -17,9 +17,6 @@ */ #pragma once -#ifndef BASESTRUCTS_H__ -#define BASESTRUCTS_H__ - #include typedef struct{ @@ -136,4 +133,3 @@ typedef struct{ int (*getMaxPos)(int *p); // amount of positions } Wheel; -#endif // BASESTRUCTS_H__ diff --git a/ccdfunc.c b/ccdfunc.c index adad194..27393a2 100644 --- a/ccdfunc.c +++ b/ccdfunc.c @@ -186,8 +186,7 @@ int saveFITS(IMG *img, char **outp){ } char buff[PATH_MAX+1], fnam[PATH_MAX+1]; if(!GP->outfile && !GP->outfileprefix){ - LOGERR("Can't save image: neither filename nor filename prefix pointed"); - WARNX(_("Neither filename nor filename prefix pointed!")); + LOGWARN("Image not saved: neither filename nor filename prefix pointed"); return FALSE; } if(GP->outfile){ // pointed specific output file name like "file.fits", check it @@ -819,6 +818,8 @@ void cancel(){ } } + +#ifdef IMAGEVIEW static volatile int grabends = 1; static void *grabnext(void *arg){ FNAME(); @@ -845,6 +846,8 @@ eof: DBG("EXIT"); } + + /** * @brief ccdcaptured - get new image data for viewer * @param img - pointer to IMG* (if IMG* is NULL, will be allocated here) @@ -894,3 +897,4 @@ int ccdcaptured(IMG **imgptr){ } return FALSE; } +#endif diff --git a/ccdfunc.h b/ccdfunc.h index 18b6976..debf9da 100644 --- a/ccdfunc.h +++ b/ccdfunc.h @@ -17,9 +17,6 @@ */ #pragma once -#ifndef CCDFUNC_H__ -#define CCDFUNC_H__ - #include "basestructs.h" extern Camera *camera; @@ -40,6 +37,7 @@ int startFocuser(void **dlh); void focclose(); void closewheel(); void closecam(); +#ifdef IMAGEVIEW int ccdcaptured(IMG **img); +#endif -#endif // CCDFUNC_H__ diff --git a/client.c b/client.c index 374c4b2..4c1cbf8 100644 --- a/client.c +++ b/client.c @@ -17,6 +17,7 @@ */ // client-side functions +#include #include // isnan #include #include @@ -30,9 +31,15 @@ static char sendbuf[BUFSIZ]; #define SENDMSG(...) do{snprintf(sendbuf, BUFSIZ-1, __VA_ARGS__); verbose(2, "\t> %s", sendbuf); sendstrmessage(sock, sendbuf); getans(sock);}while(0) -static int expstate = CAMERA_CAPTURE; +static volatile atomic_int expstate = CAMERA_CAPTURE; static int xm0,ym0,xm1,ym1; // max format +#ifdef IMAGEVIEW +static IMG ima = {0}; +static volatile atomic_int grabends = 0; +static int imdatalen = 0, imbufsz = 0; +#endif + /** * check data from fd (polling function for client) * @param fd - file descriptor @@ -104,6 +111,17 @@ static int parseans(char *ans){ sscanf(val, "%d,%d,%d,%d", &xm0, &ym0, &xm1, &ym1); DBG("Got maxformat: %d,%d,%d,%d", xm0, ym0, xm1, ym1); } +#ifdef IMAGEVIEW + else if(0 == strcmp(CMD_IMWIDTH, ans)){ + ima.w = atoi(val); + DBG("Get width: %d", ima.w); + imdatalen = ima.w * ima.h * 2; + }else if(0 == strcmp(CMD_IMHEIGHT, ans)){ + ima.h = atoi(val); + DBG("Get height: %d", ima.h); + imdatalen = ima.w * ima.h * 2; + } +#endif return FALSE; } @@ -130,7 +148,7 @@ static int getans(int sock){ /** * @brief processData - process here some actions and make messages for server */ -static void process_data(int sock){ +static void send_headers(int sock){ // common information SENDMSG(CMD_INFO); // focuser @@ -178,11 +196,15 @@ static void process_data(int sock){ else SENDMSG(CMD_DARK "=0"); } if(GP->outfile){ - SENDMSG(CMD_FILENAME "=%s", makeabspath(GP->outfile, FALSE)); + if(!*GP->outfile) SENDMSG(CMD_FILENAME "="); + else SENDMSG(CMD_FILENAME "=%s", makeabspath(GP->outfile, FALSE)); if(GP->rewrite) SENDMSG(CMD_REWRITE "=1"); else SENDMSG(CMD_REWRITE "=0"); } - if(GP->outfileprefix) SENDMSG(CMD_FILENAMEPREFIX "=%s", makeabspath(GP->outfileprefix, FALSE)); + if(GP->outfileprefix){ + if(!*GP->outfileprefix) SENDMSG(CMD_FILENAMEPREFIX "="); + else 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) @@ -213,16 +235,16 @@ void client(int sock){ SENDMSG(CMD_RESTART); return; } - process_data(sock); + send_headers(sock); 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){ + if((GP->outfile && *GP->outfile) || (GP->outfileprefix && *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); - } else { + }else{ while(getans(sock)); DBG("RETURN: no more data"); return; @@ -276,3 +298,93 @@ void client(int sock){ if(GP->waitexpend) WARNX(_("Server timeout")); DBG("Timeout"); } + +#ifdef IMAGEVIEW +static int grabsockfd = -1; +void init_grab_sock(int sock){ + grabsockfd = sock; + send_headers(sock); +} + +static void *grabnext(void _U_ *arg){ // daemon grabbing images through the net + FNAME(); + if(grabsockfd < 0) return NULL; + int sock = grabsockfd; + while(1){ + while(grabends); // wait until image processed + SENDMSG(CMD_IMWIDTH); + SENDMSG(CMD_IMHEIGHT); + expstate = CAMERA_CAPTURE; + SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); // start capture + double timeout = GP->exptime + CLIENT_TIMEOUT, t0 = dtime(); + while(dtime() - t0 < timeout){ + SENDMSG(CMD_EXPSTATE); + if(expstate != CAMERA_CAPTURE) break; + } + if(dtime() - t0 >= timeout || expstate != CAMERA_FRAMERDY){ + WARNX("Image wasn't received"); + continue; + } + DBG("Frame ready"); + sendstrmessage(sock, CMD_GETIMAGE); + if(imbufsz < imdatalen){ + DBG("Reallocate memory from %d to %d", imbufsz, imdatalen); + ima.data = realloc(ima.data, imdatalen); + imbufsz = imdatalen; + } + t0 = dtime(); + int got = 0; + while(dtime() - t0 < CLIENT_TIMEOUT){ + if(!canberead(sock)) continue; + int rd = read(sock, ((uint8_t*)ima.data)+got, imdatalen - got); + if(rd <= 0){ + WARNX("Server disconnected"); + signals(1); + } + got += rd; + DBG("Read %d bytes; total read %d from %d", rd, got, imdatalen); + if(got == imdatalen){ + DBG("Got image"); + grabends = 1; + break; + } + } + if(dtime() - t0 > CLIENT_TIMEOUT) WARNX("Timeout, image didn't received"); + } + return NULL; +} + +// try to capture images through socket +int sockcaptured(IMG **imgptr){ + if(!imgptr) return FALSE; + static pthread_t grabthread = 0; + if(grabsockfd < 0) return FALSE; + if(imgptr == (void*)-1){ // kill `grabnext` + DBG("Kill grabbing thread"); + if(grabthread){ + pthread_cancel(grabthread); + pthread_join(grabthread, NULL); + grabthread = 0; + } + DBG("Killed"); + return FALSE; + } + if(!grabthread){ // start new grab + DBG("\n\n\nStart new grab"); + if(pthread_create(&grabthread, NULL, &grabnext, NULL)){ + WARN("Can't create grabbing thread"); + grabthread = 0; + } + }else{ // grab in process + if(grabends){ // image is ready + DBG("Image ready"); + if(*imgptr && (*imgptr != &ima)) free(*imgptr); + *imgptr = &ima; + grabends = 0; + return TRUE; + } + } + return FALSE; +} +// IMAGEVIEW +#endif diff --git a/client.h b/client.h index 97d9c47..d8b22f9 100644 --- a/client.h +++ b/client.h @@ -17,10 +17,12 @@ */ #pragma once -#ifndef CLIENT_H__ -#define CLIENT_H__ + +#include "basestructs.h" // client-side functions void client(int fd); - -#endif // CLIENT_H__ +#ifdef IMAGEVIEW +void init_grab_sock(int sock); +int sockcaptured(IMG **img); +#endif diff --git a/cmdlnopts.h b/cmdlnopts.h index d0bcaa6..9331444 100644 --- a/cmdlnopts.h +++ b/cmdlnopts.h @@ -17,9 +17,6 @@ */ #pragma once -#ifndef CMDLNOPTS_H__ -#define CMDLNOPTS_H__ - #include /* @@ -86,4 +83,4 @@ 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/events.c b/events.c index 3761d24..d2d7292 100644 --- a/events.c +++ b/events.c @@ -90,11 +90,6 @@ void keyPressed(unsigned char key, int x, int y){ 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 @@ -153,7 +148,7 @@ 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 diff --git a/events.h b/events.h index 426f4ee..ed7fa0b 100644 --- a/events.h +++ b/events.h @@ -17,8 +17,6 @@ */ #pragma once -#ifndef EVENTS_H__ -#define EVENTS_H__ #include #include @@ -26,14 +24,10 @@ #include #include -extern float Z; // координата Z (zoom) +extern float Z; // Z coordinate (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/imageview.c b/imageview.c index cd2ecf0..36a947c 100644 --- a/imageview.c +++ b/imageview.c @@ -26,6 +26,7 @@ #include "ccdfunc.h" #include "cmdlnopts.h" #include "imageview.h" +#include "events.h" #include "omp.h" windowData *win = NULL; // main window (common variable for events.c) @@ -531,6 +532,7 @@ void closeGL(){ /** * @brief viewer - main viewer process * @param newimage - image refresh function + * it shouldn't `free` it's argument!!! * @return 0 if all OK */ int viewer(imagefunc newimage){ diff --git a/imageview.h b/imageview.h index 9a41767..46607f3 100644 --- a/imageview.h +++ b/imageview.h @@ -17,16 +17,14 @@ */ #pragma once -#ifndef IMAGEVIEW_H__ -#define IMAGEVIEW_H__ +#include #include #include #include #include #include "ccdfunc.h" -#include "events.h" // events from menu: // temporaly stop capture of regular sequence @@ -87,5 +85,3 @@ windowData* getWin(); typedef int (*imagefunc)(IMG**); int viewer(imagefunc); - -#endif // IMAGEVIEW_H__ diff --git a/locale/ru/LC_MESSAGES/ccd_capture.mo b/locale/ru/LC_MESSAGES/ccd_capture.mo index 817f0b42904d0b74c3e9d18071acc7911e9bb538..ab7882c02fd8154e4f6b0a00cc1a8b12a3885bc1 100644 GIT binary patch delta 2724 zcmYk+Z%oxy9LMqRm8iV zmOq-ju~h#FqxBPa5xIV|bGS5~AKK4}X4yE70gOvBOUH$H2bSRNSci9Fi#y+ob2)wm z({K>y;dxwuU*aM&&nD>Pa3bM0v-ucA4H&}3*p7Pf0P=vnaL2j`VsQ0`Vllot$qnhPW zaJsf0wZaa(2M17_?ILQxad$qM!e((?hMHhA@@EJ6(Q|{S=SENi|LIK1n%Z0WSmJSE z9UY~r&pCuj)z_%a_bY0GH&GeMWLcEeR-mreqxMcKGB?|Yn$YX0_kQG#$55s5aZ&fB zp{JP@(<#OV)bSDIOS03bfre2vzU;1#Biq9!-Sv5-OA{zW?ST+#Vp~zqccT9D9d*|) zIKRlD{z}m(Cp561!t23o)Nv7N<@H#Hy?7r+oHv}=+*Hc>M$~{WBd@eKQJMT4waLd& z_eHS-bMnZ)Rx&`I^x)g52O`Klb`_QK|4=UsESdTY*P!;w2BfUE2etVIQ1^X;O7S(+ z=A6V@46<6fwjT@elt)M3^>^;VHPm-Gn;j%G(T_ol!(!A*R$v0wpfc8gx_>+JSy?yg zy|1F~KZPp6Ijq1@WKHH}@GY&SQ-xY-KdP2*;2L}%**A6*DYs?t38(}s(T7hHy~J)J zo>)ihC!Qk`3GExTJw!dBe`YFeCqafAVQK=gj{BL3J;Xjj^-?P%G{J2|C84aSWPQYg z#43V0T7UTa__V5*=qbTP#Ps$o2W%R9!JX80Ra5TN+KJY1c0z&IMz2n%rnP72YkN#@ zD)Xc6!~rL{iEV=|*hLh(^D6yQ!~?_(LKSKvl89Y|{ts3YBwo3mN{`C-5V3)HoVcHO zo~R8+69O}9=&cVYCkDJ7^vVfs2Q}?awH899rsDPlv6UzxRAsdW;t;Wu*i5MLS;Sg5 zzpD21R^<*JMr|qALUxeeUg9z0MMC@RFwsG%Z6{U}S;Qvd5#mWgEkraE8;7HbwX=qI NrnIIEPb~U9{(pmF?@0gv delta 2821 zcmYk+e@s?Y9LMo5Jeq)6@WL3GitUu`(>@tHR&(5-k-;_#@X|IUgw^B@44rE&$;*a zW#^XrKPC)2Xq5fLI3jPD*#}q{!yn~(oLMH`z;sL;X_kaja155VeDf9&AQ+{1$S9eeTZxfEw^1>Oo^inI&K@ z#$yp`faO?-HJFR@G@#f?Kl=cMGdsq zwckW#D3-KnLK&!m%)t9_F{+;bpk_J~HGneI z0BSG?Tk&q}LdIg>p$76RlB`H4x^5Jm`5MtQDx9+_=QiYLE&TCpJA|6iyQrCe>Fh-f z#f_CXjz^suyTb2S-pN{TMZ)FfPTvaXJ>$n{0A+ z;JqAQL9J~ZPt|=7p!UovWOZ#jDkCkp8jm4kwGm^;|5PezEKnYnp;FU~O6?KUQXEHR zq93(X*PJ>~$0?}$3sGxZiyFv2oQ?0HW_%T=V1SF*_g3IjQ3u7S3{)f6SQ7@Y6{E2Y zwRR!Yb?vB>b|RCplc>GYhnn#}s2N6)PGu$$i?G-o@4-nN`|ndByVi&5@Hf{kgC`V;x1Exlq9YDRd9h}sIdy%BrpQr%^SXT`o6?NYv)I=+gTWvdXpKonc^nees z0K=&Fd=Pbm$0(@Ud{lcS&cYVd3{IeCcnv4x7<$!Gl%NK-g+F~yUUPOLm)b>~rT71O zq(WybwAQQ|X|h*PGdzkD@hoby4WJ%4o&{BV8G6`+8sH)1XJ7EA^Zls%0-pQAIu~Jv z&xsl;)9^)9s*XFapi&jX@U{7}Py@_IWn=}i%+~16x1#pWVPuTfg&NQWRKGXf@i-c_ zG{xxa!U`%%NdxBNtEkkUbnQPQZq#VXzTov48vK<$NNs0o~K z=X+4!onNxazb;7PX>uYeRYjocnR;vEE?tG&K8``@n@(3|A9Qy z0;EA1oq*cxb92bQE-a^^4qrmeqmVUqS!I&a4M>O9_sb1bMD4r9JgTr529xB2FBu1 zRK`9*-S;)>?dn7IdmVLs6t9k!z#mQJK`KSaq-_U2jP0nI{)AdfZTVtILH3a?N4ACS zK&AdLM&UZ5iP%KM5Srz4#8x7X(7sXGOe`glk*}K8dLy9}tCZa0|Nr6C8j0+QcFA=ijU3p ztEiQ!X-HX5UHeHzNmJ1>KM|>s94EPnY=ae8PvpCHt#A!7hlnP$Ld%JfL>-~;;auXO zTe)U~bD-rbB`S#3#5|&zSQNS(n?8I2wZ);q*mQp_wV8yrgNpX2%F~2anw?;k#42JM z5m{v{C-xB4#48)~(OmLhlXC~8Z&vcR6FwuM+p>>{+y_7NKhl{JL6lt(;C zEFpq~$|J;6#A98T;}+hQ7p!euAKdEI)NTycS8fV=^_zzrG;9sl)HZt!n``SEgVmW` y+3{=Qv%_Ba+\n" "Language-Team: LANGUAGE \n" @@ -269,326 +269,322 @@ msgstr "" msgid "Camera device unknown" msgstr "" -#: ccdfunc.c:190 -msgid "Neither filename nor filename prefix pointed!" -msgstr "" - #. п²п╣ п╪п╬пЁя┐ я│п╬я┘я─п╟п╫п╦я┌я▄ я└п╟п╧п╩ -#: ccdfunc.c:209 +#: ccdfunc.c:208 #, c-format msgid "Can't save file with prefix %s" msgstr "" -#: ccdfunc.c:357 +#: ccdfunc.c:356 #, c-format msgid "File saved as '%s'" msgstr "" -#: ccdfunc.c:366 +#: ccdfunc.c:365 msgid "Error saving file" msgstr "" -#: ccdfunc.c:406 +#: ccdfunc.c:405 #, c-format msgid "Image stat:\n" msgstr "" -#: ccdfunc.c:414 +#: ccdfunc.c:413 msgid "Focuser device not pointed" msgstr "" -#: ccdfunc.c:421 +#: ccdfunc.c:420 msgid "No focusers found" msgstr "" -#: ccdfunc.c:452 +#: ccdfunc.c:451 #, c-format msgid "Found %d focusers, you point number %d" msgstr "" -#: ccdfunc.c:456 +#: ccdfunc.c:455 msgid "Can't set active focuser number" msgstr "" -#: ccdfunc.c:470 +#: ccdfunc.c:469 msgid "Can't get focuser limit positions" msgstr "" -#: ccdfunc.c:477 +#: ccdfunc.c:476 msgid "Can't get current focuser position" msgstr "" -#: ccdfunc.c:491 +#: ccdfunc.c:490 #, c-format msgid "Can't set position %g: out of limits [%g, %g]" msgstr "" -#: ccdfunc.c:495 +#: ccdfunc.c:494 msgid "Can't home focuser" msgstr "" -#: ccdfunc.c:497 +#: ccdfunc.c:496 #, c-format msgid "Can't set position %g" msgstr "" -#: ccdfunc.c:505 +#: ccdfunc.c:504 msgid "Wheel device not pointed" msgstr "" -#: ccdfunc.c:512 +#: ccdfunc.c:511 msgid "No wheels found" msgstr "" -#: ccdfunc.c:543 +#: ccdfunc.c:542 #, c-format msgid "Found %d wheels, you point number %d" msgstr "" -#: ccdfunc.c:547 +#: ccdfunc.c:546 msgid "Can't set active wheel number" msgstr "" -#: ccdfunc.c:563 +#: ccdfunc.c:562 msgid "Can't get max wheel position" msgstr "" -#: ccdfunc.c:570 +#: ccdfunc.c:569 #, c-format msgid "Wheel position should be from 0 to %d" msgstr "" -#: ccdfunc.c:574 +#: ccdfunc.c:573 #, c-format msgid "Can't set wheel position %d" msgstr "" -#: ccdfunc.c:591 +#: ccdfunc.c:590 #, c-format msgid "%.1f seconds till exposition ends" msgstr "" -#: ccdfunc.c:605 +#: ccdfunc.c:604 msgid "Camera device not pointed" msgstr "" -#: ccdfunc.c:612 ccdfunc.c:613 +#: ccdfunc.c:611 ccdfunc.c:612 msgid "No cameras found" msgstr "" -#: ccdfunc.c:643 +#: ccdfunc.c:642 #, c-format msgid "Found %d cameras, you point number %d" msgstr "" -#: ccdfunc.c:647 +#: ccdfunc.c:646 msgid "Can't set active camera number" msgstr "" -#: ccdfunc.c:653 +#: ccdfunc.c:652 msgid "Can't set fan speed" msgstr "" -#: ccdfunc.c:654 +#: ccdfunc.c:653 #, c-format msgid "Set fan speed to %d" msgstr "" -#: ccdfunc.c:659 +#: ccdfunc.c:658 #, c-format msgid "Camera model: %s" msgstr "" -#: ccdfunc.c:660 +#: ccdfunc.c:659 #, c-format msgid "Pixel size: %g x %g" msgstr "" -#: ccdfunc.c:666 +#: ccdfunc.c:665 #, c-format msgid "Full array: %s" msgstr "" -#: ccdfunc.c:669 +#: ccdfunc.c:668 #, c-format msgid "Field of view: %s" msgstr "" -#: ccdfunc.c:672 +#: ccdfunc.c:671 #, c-format msgid "Current format: %s" msgstr "" -#: ccdfunc.c:675 +#: ccdfunc.c:674 #, c-format msgid "Can't set T to %g degC" msgstr "" -#: ccdfunc.c:683 +#: ccdfunc.c:682 #, c-format msgid "Shutter command: %s\n" msgstr "" -#: ccdfunc.c:685 +#: ccdfunc.c:684 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr "" #. "п÷п╬п©я▀я┌п╨п╟ я│п╨п╬п╫я└п╦пЁя┐я─п╦я─п╬п╡п╟я┌я▄ п©п╬я─я┌ I/O п╨п╟п╨ %d\n" -#: ccdfunc.c:689 +#: ccdfunc.c:688 #, c-format msgid "Try to configure I/O port as %d" msgstr "" -#: ccdfunc.c:691 +#: ccdfunc.c:690 msgid "Can't configure (unsupported?)" msgstr "" -#: ccdfunc.c:698 +#: ccdfunc.c:697 msgid "Can't get IOport state (unsupported?)" msgstr "" #. "п÷п╬п©я▀я┌п╨п╟ п╥п╟п©п╦я│п╦ %d п╡ п©п╬я─я┌ I/O\n" -#: ccdfunc.c:702 +#: ccdfunc.c:701 #, c-format msgid "Try to write %d to I/O port" msgstr "" -#: ccdfunc.c:704 +#: ccdfunc.c:703 msgid "Can't set IOport" msgstr "" -#: ccdfunc.c:711 +#: ccdfunc.c:710 #, c-format msgid "Set gain to %g" msgstr "" -#: ccdfunc.c:712 +#: ccdfunc.c:711 #, c-format msgid "Can't set gain to %g" msgstr "" -#: ccdfunc.c:717 +#: ccdfunc.c:716 #, c-format msgid "Set brightness to %g" msgstr "" -#: ccdfunc.c:718 +#: ccdfunc.c:717 #, c-format msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:726 server.c:223 +#: ccdfunc.c:725 server.c:230 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:738 server.c:224 +#: ccdfunc.c:737 server.c:231 msgid "Can't set given geometry" msgstr "" -#: ccdfunc.c:742 +#: ccdfunc.c:741 #, c-format msgid "Can't set %d flushes" msgstr "" -#: ccdfunc.c:746 +#: ccdfunc.c:745 #, c-format msgid "Can't set exposure time to %f seconds" msgstr "" -#: ccdfunc.c:749 +#: ccdfunc.c:748 msgid "Can't change frame type" msgstr "" -#: ccdfunc.c:752 +#: ccdfunc.c:751 msgid "Can't set bit depth" msgstr "" -#: ccdfunc.c:754 +#: ccdfunc.c:753 msgid "Can't set readout speed" msgstr "" -#: ccdfunc.c:755 +#: ccdfunc.c:754 #, c-format msgid "Readout mode: %s" msgstr "" -#: ccdfunc.c:756 +#: ccdfunc.c:755 msgid "Only show statistics" msgstr "" #. GET binning should be AFTER setgeometry! -#: ccdfunc.c:758 +#: ccdfunc.c:757 msgid "Can't get current binning" msgstr "" #. п≈п╟я┘п╡п╟я┌ п╨п╟п╢я─п╟ %d\n -#: ccdfunc.c:780 +#: ccdfunc.c:779 #, c-format msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:782 ccdfunc.c:830 server.c:121 +#: ccdfunc.c:781 ccdfunc.c:831 server.c:125 msgid "Can't start exposition" msgstr "" -#: ccdfunc.c:786 +#: ccdfunc.c:785 msgid "Can't capture image" msgstr "" -#: ccdfunc.c:789 +#: ccdfunc.c:788 msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:792 ccdfunc.c:838 +#: ccdfunc.c:791 ccdfunc.c:839 msgid "Can't grab image" msgstr "" #. %d я│п╣п╨я┐п╫п╢ п╢п╬ п╬п╨п╬п╫я┤п╟п╫п╦я▐ п©п╟я┐п╥я▀\n -#: ccdfunc.c:801 client.c:260 +#: ccdfunc.c:800 client.c:282 #, c-format msgid "%d seconds till pause ends\n" msgstr "" -#: server.c:163 +#: server.c:168 msgid "No camera device" msgstr "" -#: client.c:247 +#: client.c:269 msgid "Can't make exposition" msgstr "" -#: client.c:276 +#: client.c:298 msgid "Server timeout" msgstr "" -#: imageview.c:49 +#: imageview.c:50 msgid "Already initialized!" msgstr "" -#: imageview.c:285 +#: imageview.c:286 msgid "Can't init mutex!" msgstr "" -#: imageview.c:387 +#: imageview.c:388 #, c-format msgid "Histogram conversion: %s" msgstr "" -#: imageview.c:507 imageview.c:579 +#: imageview.c:508 imageview.c:581 #, c-format msgid "Equalization of histogram: %s" msgstr "" -#: imageview.c:507 imageview.c:579 +#: imageview.c:508 imageview.c:581 msgid "on" msgstr "" -#: imageview.c:507 imageview.c:579 +#: imageview.c:508 imageview.c:581 msgid "off" msgstr "" -#: imageview.c:545 +#: imageview.c:547 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 35c9f25..dbc5704 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-02-07 16:54+0300\n" + "POT-Creation-Date: 2023-02-28 17:05+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,18 +16,18 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n" "Content-Type: text/plain; charset=koi8-r\n" "Content-Transfer-Encoding: 8bit\n" -#: ccdfunc.c:591 +#: ccdfunc.c:590 #, c-format msgid "%.1f seconds till exposition ends" msgstr "%.1f секунд до окончания экспозиции" #. %d я│п╣п╨я┐п╫п╢ п╢п╬ п╬п╨п╬п╫я┤п╟п╫п╦я▐ п©п╟я┐п╥я▀\n -#: ccdfunc.c:801 client.c:260 +#: ccdfunc.c:800 client.c:282 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d секунд до окончания паузы\n" -#: imageview.c:49 +#: imageview.c:50 msgid "Already initialized!" msgstr "Уже инициализировано!" @@ -39,7 +39,7 @@ msgstr " msgid "CMOS gain level" msgstr "уровень Gain CMOS" -#: ccdfunc.c:605 +#: ccdfunc.c:604 msgid "Camera device not pointed" msgstr "Устройство свеоприемника не подключено" @@ -47,20 +47,20 @@ msgstr " msgid "Camera device unknown" msgstr "Устройство свеоприемника не опознано" -#: ccdfunc.c:659 +#: ccdfunc.c:658 #, c-format msgid "Camera model: %s" msgstr "Модель светоприемника: %s" -#: ccdfunc.c:786 +#: ccdfunc.c:785 msgid "Can't capture image" msgstr "Не могу захватить изображение" -#: ccdfunc.c:749 +#: ccdfunc.c:748 msgid "Can't change frame type" msgstr "Не могу изменить тип кадра" -#: ccdfunc.c:691 +#: ccdfunc.c:690 msgid "Can't configure (unsupported?)" msgstr "Не могу сконфигурировать (опция не поддерживается?)" @@ -84,146 +84,146 @@ msgstr " msgid "Can't find wheel in plugin %s: %s" msgstr "Не могу найти плагин турели %s: %s" -#: ccdfunc.c:698 +#: ccdfunc.c:697 msgid "Can't get IOport state (unsupported?)" msgstr "Не могу получить состояние порта I/O (не поддерживается?)" #. GET binning should be AFTER setgeometry! -#: ccdfunc.c:758 +#: ccdfunc.c:757 msgid "Can't get current binning" msgstr "Не могу получить текущее значение биннинга" -#: ccdfunc.c:477 +#: ccdfunc.c:476 msgid "Can't get current focuser position" msgstr "Не могу определить текущую позицию фокусера" -#: ccdfunc.c:470 +#: ccdfunc.c:469 msgid "Can't get focuser limit positions" msgstr "Не могу определить предельную позицию фокусера" -#: ccdfunc.c:563 +#: ccdfunc.c:562 msgid "Can't get max wheel position" msgstr "Не могу определить предельную позицию колеса" -#: ccdfunc.c:792 ccdfunc.c:838 +#: ccdfunc.c:791 ccdfunc.c:839 msgid "Can't grab image" msgstr "Не могу захватить изображение" -#: ccdfunc.c:495 +#: ccdfunc.c:494 msgid "Can't home focuser" msgstr "Не могу установить фокусер в нуль" -#: imageview.c:285 +#: imageview.c:286 msgid "Can't init mutex!" msgstr "Не могу инициализировать мьютекс!" -#: client.c:247 +#: client.c:269 msgid "Can't make exposition" msgstr "Не могу выполнить экспозицию" -#: imageview.c:545 +#: imageview.c:547 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "Не могу открыть окно OpenGL, отображение будет недоступно" -#: ccdfunc.c:685 +#: ccdfunc.c:684 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr "Не могу выполнить команду затвора %s (не поддерживается?)" #. п²п╣ п╪п╬пЁя┐ я│п╬я┘я─п╟п╫п╦я┌я▄ я└п╟п╧п╩ -#: ccdfunc.c:209 +#: ccdfunc.c:208 #, c-format msgid "Can't save file with prefix %s" msgstr "Не могу сохранить файл с префиксом %s" -#: ccdfunc.c:742 +#: ccdfunc.c:741 #, c-format msgid "Can't set %d flushes" msgstr "Не могу установить %d сбросов" -#: ccdfunc.c:704 +#: ccdfunc.c:703 msgid "Can't set IOport" msgstr "Не могу поменять значения порта I/O" -#: ccdfunc.c:675 +#: ccdfunc.c:674 #, c-format msgid "Can't set T to %g degC" msgstr "Не могу установить температуру в %g градЦ" -#: ccdfunc.c:647 +#: ccdfunc.c:646 msgid "Can't set active camera number" msgstr "Не могу установить номер активной камеры" -#: ccdfunc.c:456 +#: ccdfunc.c:455 msgid "Can't set active focuser number" msgstr "Не могу установить номер активного фокусера" -#: ccdfunc.c:547 +#: ccdfunc.c:546 msgid "Can't set active wheel number" msgstr "Не могу установить номер активного колеса" -#: ccdfunc.c:726 server.c:223 +#: ccdfunc.c:725 server.c:230 #, c-format msgid "Can't set binning %dx%d" msgstr "Не могу установить биннинг %dx%d" -#: ccdfunc.c:752 +#: ccdfunc.c:751 msgid "Can't set bit depth" msgstr "Не могу установить разрядность АЦП" -#: ccdfunc.c:718 +#: ccdfunc.c:717 #, c-format msgid "Can't set brightness to %g" msgstr "Не могу установить яркость в %g" -#: ccdfunc.c:746 +#: ccdfunc.c:745 #, c-format msgid "Can't set exposure time to %f seconds" msgstr "Не могу установить экспозицию в %f секунд" -#: ccdfunc.c:653 +#: ccdfunc.c:652 msgid "Can't set fan speed" msgstr "Не могу установить скорость вентиляторов" -#: ccdfunc.c:712 +#: ccdfunc.c:711 #, c-format msgid "Can't set gain to %g" msgstr "Не могу установить Gain в %g" -#: ccdfunc.c:738 server.c:224 +#: ccdfunc.c:737 server.c:231 msgid "Can't set given geometry" msgstr "Не могу установить геометрию" -#: ccdfunc.c:497 +#: ccdfunc.c:496 #, c-format msgid "Can't set position %g" msgstr "Не могу изменить позицию на %g" -#: ccdfunc.c:491 +#: ccdfunc.c:490 #, c-format msgid "Can't set position %g: out of limits [%g, %g]" msgstr "Не могу установить позицию %g: вне пределов [%g, %g]" -#: ccdfunc.c:754 +#: ccdfunc.c:753 msgid "Can't set readout speed" msgstr "Не могу установить скорость считывания" -#: ccdfunc.c:574 +#: ccdfunc.c:573 #, c-format msgid "Can't set wheel position %d" msgstr "Не могу установить положение колеса %d" -#: ccdfunc.c:782 ccdfunc.c:830 server.c:121 +#: ccdfunc.c:781 ccdfunc.c:831 server.c:125 msgid "Can't start exposition" msgstr "Не могу начать экспозицию" #. п≈п╟я┘п╡п╟я┌ п╨п╟п╢я─п╟ %d\n -#: ccdfunc.c:780 +#: ccdfunc.c:779 #, c-format msgid "Capture frame %d" msgstr "Захват кадра %d" -#: ccdfunc.c:672 +#: ccdfunc.c:671 #, c-format msgid "Current format: %s" msgstr "" @@ -232,55 +232,55 @@ msgstr "" msgid "Display image in OpenGL window" msgstr "Отображение изображения в окне OpenGL" -#: imageview.c:507 imageview.c:579 +#: imageview.c:508 imageview.c:581 #, c-format msgid "Equalization of histogram: %s" msgstr "Эквализация гистограммы: %s" -#: ccdfunc.c:366 +#: ccdfunc.c:365 msgid "Error saving file" msgstr "Ошибка сохранения файла" -#: ccdfunc.c:669 +#: ccdfunc.c:668 #, c-format msgid "Field of view: %s" msgstr "Поле зрения: %s" -#: ccdfunc.c:357 +#: ccdfunc.c:356 #, c-format msgid "File saved as '%s'" msgstr "Файл сохранен как '%s'" -#: ccdfunc.c:414 +#: ccdfunc.c:413 msgid "Focuser device not pointed" msgstr "Устройство фокусера не указано" -#: ccdfunc.c:643 +#: ccdfunc.c:642 #, c-format msgid "Found %d cameras, you point number %d" msgstr "Обнаружено %d камер, вы указали %d" -#: ccdfunc.c:452 +#: ccdfunc.c:451 #, c-format msgid "Found %d focusers, you point number %d" msgstr "Обнаружено %d фокусеров, вы указали %d" -#: ccdfunc.c:543 +#: ccdfunc.c:542 #, c-format msgid "Found %d wheels, you point number %d" msgstr "Обнаружено %d колес, вы указали %d" -#: ccdfunc.c:666 +#: ccdfunc.c:665 #, c-format msgid "Full array: %s" msgstr "Полный формат: %s" -#: imageview.c:387 +#: imageview.c:388 #, c-format msgid "Histogram conversion: %s" msgstr "Преобразование гистограммы: %s" -#: ccdfunc.c:406 +#: ccdfunc.c:405 #, c-format msgid "Image stat:\n" msgstr "Статистика по изображению: \n" @@ -289,27 +289,23 @@ msgstr " msgid "N flushes before exposing (default: 1)" msgstr "N засвечиваний перед экспозицией (по умолчанию: 1)" -#: ccdfunc.c:190 -msgid "Neither filename nor filename prefix pointed!" -msgstr "Ни имя файла, ни префикс не указаны!" - -#: server.c:163 +#: server.c:168 msgid "No camera device" msgstr "Не указано устройство камеры" -#: ccdfunc.c:612 ccdfunc.c:613 +#: ccdfunc.c:611 ccdfunc.c:612 msgid "No cameras found" msgstr "Камер не обнаружено" -#: ccdfunc.c:421 +#: ccdfunc.c:420 msgid "No focusers found" msgstr "Фокусеров не обнаружено" -#: ccdfunc.c:512 +#: ccdfunc.c:511 msgid "No wheels found" msgstr "Турелей не обнаружено" -#: ccdfunc.c:756 +#: ccdfunc.c:755 msgid "Only show statistics" msgstr "Только отобразить статистику" @@ -317,52 +313,52 @@ msgstr " msgid "PID file (default: " msgstr "PID-файл (по умолчанию: " -#: ccdfunc.c:660 +#: ccdfunc.c:659 #, c-format msgid "Pixel size: %g x %g" msgstr "Размер пикселя: %g x %g" -#: ccdfunc.c:789 +#: ccdfunc.c:788 msgid "Read grabbed image" msgstr "Считывание изображения" -#: ccdfunc.c:755 +#: ccdfunc.c:754 #, c-format msgid "Readout mode: %s" msgstr "Режим считывания: %s" -#: client.c:276 +#: client.c:298 msgid "Server timeout" msgstr "Таймаут сервера" -#: ccdfunc.c:717 +#: ccdfunc.c:716 #, c-format msgid "Set brightness to %g" msgstr "Установить яркость в %g" -#: ccdfunc.c:654 +#: ccdfunc.c:653 #, c-format msgid "Set fan speed to %d" msgstr "Не могу установить скорость вентиляторов в %d" -#: ccdfunc.c:711 +#: ccdfunc.c:710 #, c-format msgid "Set gain to %g" msgstr "Установить Gain в %g" -#: ccdfunc.c:683 +#: ccdfunc.c:682 #, c-format msgid "Shutter command: %s\n" msgstr "Команда затвора: %s\n" #. "п÷п╬п©я▀я┌п╨п╟ я│п╨п╬п╫я└п╦пЁя┐я─п╦я─п╬п╡п╟я┌я▄ п©п╬я─я┌ I/O п╨п╟п╨ %d\n" -#: ccdfunc.c:689 +#: ccdfunc.c:688 #, c-format msgid "Try to configure I/O port as %d" msgstr "Попытка сконфигурировать порт I/O как %d" #. "п÷п╬п©я▀я┌п╨п╟ п╥п╟п©п╦я│п╦ %d п╡ п©п╬я─я┌ I/O\n" -#: ccdfunc.c:702 +#: ccdfunc.c:701 #, c-format msgid "Try to write %d to I/O port" msgstr "Попытка записи %d в порт I/O" @@ -371,11 +367,11 @@ msgstr " msgid "UNIX socket name" msgstr "Имя UNIX-сокета" -#: ccdfunc.c:505 +#: ccdfunc.c:504 msgid "Wheel device not pointed" msgstr "Устройство турели не указано" -#: ccdfunc.c:570 +#: ccdfunc.c:569 #, c-format msgid "Wheel position should be from 0 to %d" msgstr "Позиция колеса должна быть от 0 до %d" @@ -509,11 +505,11 @@ msgstr " msgid "observing program name" msgstr "название программы" -#: imageview.c:507 imageview.c:579 +#: imageview.c:508 imageview.c:581 msgid "off" msgstr "выкл" -#: imageview.c:507 imageview.c:579 +#: imageview.c:508 imageview.c:581 msgid "on" msgstr "вкл" @@ -592,3 +588,6 @@ msgstr " #: cmdlnopts.c:46 msgid "wheel device plugin (e.g. devdummy.so)" msgstr "плагин устройства турели (например, devdummy.so)" + +#~ msgid "Neither filename nor filename prefix pointed!" +#~ msgstr "Ни имя файла, ни префикс не указаны!" diff --git a/main.c b/main.c index ef51fd0..d2f40e2 100644 --- a/main.c +++ b/main.c @@ -131,12 +131,8 @@ int main(int argc, char **argv){ wheels(); camerainit = prepare_ccds(); }else{ // client mode -#ifdef IMAGEVIEW - if(GP->showimage) return viewer(NULL); // TODO -#endif if(GP->path) return start_socket(isserver, GP->path, FALSE); if(GP->port) return start_socket(isserver, GP->port, TRUE); - } #ifdef IMAGEVIEW if(GP->showimage){ // activate image vindow in capture or simple viewer mode diff --git a/omp.h b/omp.h index 71101f4..a4d3801 100644 --- a/omp.h +++ b/omp.h @@ -17,8 +17,6 @@ */ #pragma once -#ifndef OMP_H__ -#define OMP_H__ #ifdef OMP_FOUND #include @@ -34,4 +32,3 @@ #endif -#endif // OMP_H__ diff --git a/server.c b/server.c index 180d1f0..1e2643c 100644 --- a/server.c +++ b/server.c @@ -70,9 +70,12 @@ strpair allcommands[] = { { CMD_FGOTO, "focuser position" }, { CMD_FRAMEFORMAT, "camera frame format (X0,Y0,X1,Y1)" }, { CMD_GAIN, "camera gain" }, + { CMD_GETIMAGE, "get image (binary data 2*w*h bytes)" }, { CMD_HBIN, "horizontal binning" }, { CMD_HEADERFILES, "add FITS records from these files (comma-separated list)" }, { CMD_HELP, "show this help" }, + { CMD_IMHEIGHT, "last image height" }, + { CMD_IMWIDTH, "last image width" }, { CMD_INFO, "connected devices state" }, { CMD_INSTRUMENT, "FITS 'INSTRUME' field" }, { CMD_IO, "get/set camera IO" }, @@ -141,17 +144,18 @@ static inline void cameracapturestate(){ // capturing - wait for exposition ends // now save frame if(!ima.data) LOGERR("Can't save image: not initialized"); else{ - if(!camera->capture(&ima)) LOGERR("Can't capture image"); - else{ + if(!camera->capture(&ima)){ + LOGERR("Can't capture image"); + camstate = CAMERA_ERROR; + return; + }else{ calculate_stat(&ima); if(saveFITS(&ima, &lastfile)){ DBG("LAST file name changed"); - camstate = CAMERA_FRAMERDY; - return; } } } - camstate = CAMERA_ERROR; + camstate = CAMERA_FRAMERDY; } } } @@ -217,6 +221,8 @@ static int camdevini(int n){ frameformat step; camera->getgeomlimits(&frmformatmax, &step); curformat = frmformatmax; + DBG("\n\nGeometry format (offx/offy) w/h: (%d/%d) %d/%d", curformat.xoff, curformat.yoff, + curformat.w, curformat.h); if(GP->hbin < 1) GP->hbin = 1; if(GP->vbin < 1) GP->vbin = 1; fixima(); @@ -302,14 +308,17 @@ static hresult exphandler(int fd, _U_ const char *key, const char *val){ // show last filename of saved FITS static hresult lastfnamehandler(int fd, _U_ const char *key, _U_ const char *val){ char buf[PATH_MAX+32]; - snprintf(buf, PATH_MAX+31, CMD_LASTFNAME "=%s", lastfile); + if(lastfile && *lastfile) snprintf(buf, PATH_MAX+31, CMD_LASTFNAME "=%s", lastfile); + else snprintf(buf, PATH_MAX+31, CMD_LASTFNAME "="); if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } // filename setter/getter static hresult namehandler(int fd, _U_ const char *key, const char *val){ char buf[PATH_MAX+32]; - if(val){ + DBG("filename=%s", val); + if(val && *val){ + DBG("Make abs path"); char *path = makeabspath(val, FALSE); if(!path){ LOGERR("Can't create file '%s'", val); @@ -319,6 +328,11 @@ static hresult namehandler(int fd, _U_ const char *key, const char *val){ outfile = strdup(path); GP->outfile = outfile; GP->outfileprefix = NULL; + }else{ // clear names + DBG("Clear names"); + GP->outfileprefix = NULL; + GP->outfile = NULL; + return RESULT_OK; } if(!GP->outfile) return RESULT_FAIL; snprintf(buf, PATH_MAX+31, CMD_FILENAME "=%s", GP->outfile); @@ -328,6 +342,7 @@ static hresult namehandler(int fd, _U_ const char *key, const char *val){ // filename prefix static hresult nameprefixhandler(_U_ int fd, _U_ const char *key, const char *val){ char buf[PATH_MAX+32]; + DBG("filename prefix=%s", val); if(val){ char *path = makeabspath(val, FALSE); if(!path){ @@ -339,6 +354,10 @@ static hresult nameprefixhandler(_U_ int fd, _U_ const char *key, const char *va outfile = strdup(path); GP->outfileprefix = outfile; GP->outfile = NULL; + }else{ // clear names + GP->outfileprefix = NULL; + GP->outfile = NULL; + return RESULT_OK; } if(!GP->outfileprefix) return RESULT_FAIL; snprintf(buf, PATH_MAX+31, CMD_FILENAMEPREFIX "=%s", GP->outfileprefix); @@ -378,7 +397,7 @@ static hresult binhandler(_U_ int fd, const char *key, const char *val){ } return RESULT_FAIL; } -static hresult temphandler(_U_ int fd, _U_ const char *key, const char *val){ +static hresult temphandler(int fd, _U_ const char *key, const char *val){ float f; char buf[64]; int r; @@ -408,7 +427,7 @@ static hresult temphandler(_U_ int fd, _U_ const char *key, const char *val){ return RESULT_SILENCE; }else return RESULT_FAIL; } -static hresult camfanhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ +static hresult camfanhandler(int fd, _U_ const char *key, _U_ const char *val){ char buf[64]; if(val){ int spd = atoi(val); @@ -497,7 +516,7 @@ static hresult formathandler(int fd, const char *key, const char *val){ char buf[64]; frameformat fmt; if(val){ - if(strcmp(key, CMD_FRAMEFORMAT)) return RESULT_BADKEY; // can't set maxformat + if(strcmp(key, CMD_FRAMEMAX)) return RESULT_BADKEY; // can't set maxformat if(4 != sscanf(val, "%d,%d,%d,%d", &fmt.xoff, &fmt.yoff, &fmt.w, &fmt.h)) return RESULT_BADVAL; fmt.w -= fmt.xoff; fmt.h -= fmt.yoff; int r = camera->setgeometry(&fmt); @@ -861,6 +880,23 @@ static hresult helphandler(int fd, _U_ const char *key, _U_ const char *val){ return RESULT_SILENCE; } +// sent to client last image +static hresult imsendhandler(int fd, _U_ const char *key, _U_ const char *val){ + if(!ima.data || !ima.h || !ima.w) return RESULT_FAIL; + // send image as raw data w*h*2 + if(!sendimage(fd, ima.data, 2*ima.h*ima.w)) return RESULT_DISCONNECTED; + return RESULT_OK; +} + +static hresult imsizehandler(int fd, const char *key, _U_ const char *val){ + char buf[64]; + // send image width/height in pixels + if(0 == strcmp(key, CMD_IMHEIGHT)) snprintf(buf, 63, CMD_IMHEIGHT "=%d", ima.h); + else snprintf(buf, 63, CMD_IMWIDTH "=%d", ima.w); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; + return RESULT_OK; +} + // for setters: do nothing when camera not in idle state static int CAMbusy(){ if(camera && camstate != CAMERA_IDLE){ @@ -909,6 +945,9 @@ static handleritem items[] = { {chkcam, formathandler, CMD_FRAMEMAX}, {chkcam, nflusheshandler, CMD_NFLUSHES}, {NULL, expstatehandler, CMD_EXPSTATE}, + {NULL, imsendhandler, CMD_GETIMAGE}, + {NULL, imsizehandler, CMD_IMWIDTH}, + {NULL, imsizehandler, CMD_IMHEIGHT}, {chkcam, nameprefixhandler, CMD_FILENAMEPREFIX}, {chkcam, rewritefilehandler, CMD_REWRITE}, {chkcam, _8bithandler, CMD_8BIT}, diff --git a/server.h b/server.h index 845158b..4efefd3 100644 --- a/server.h +++ b/server.h @@ -17,8 +17,6 @@ */ #pragma once -#ifndef SERVER_H__ -#define SERVER_H__ typedef enum{ CAMERA_IDLE, // idle state, client send this to cancel capture @@ -39,6 +37,11 @@ char *makeabspath(const char *path, int shouldbe); #define CMD_HELP "help" // restart server #define CMD_RESTART "restartTheServer" +// get last exposed image +#define CMD_GETIMAGE "getimage" +// get image size in pixels +#define CMD_IMWIDTH "imheight" +#define CMD_IMHEIGHT "imwidth" // CCD/CMOS #define CMD_CAMLIST "camlist" @@ -85,5 +88,3 @@ char *makeabspath(const char *path, int shouldbe); #define CMD_WLIST "wlist" #define CMD_WDEVNO "wdevno" #define CMD_WPOS "wpos" - -#endif // SERVER_H__ diff --git a/socket.c b/socket.c index 833ca65..63eea06 100644 --- a/socket.c +++ b/socket.c @@ -24,8 +24,11 @@ #include // unix socket #include -#include "cmdlnopts.h" #include "client.h" +#include "cmdlnopts.h" +#ifdef IMAGEVIEW +#include "imageview.h" +#endif #include "server.h" #include "socket.h" @@ -114,13 +117,34 @@ int start_socket(int isserver, char *path, int isnet){ } if(isnet) freeaddrinfo(res); if(isserver) server(sock); - else client(sock); + else{ +#ifdef IMAGEVIEW + if(GP->showimage){ + init_grab_sock(sock); + viewer(sockcaptured); // start viewer with socket client parser + }else +#endif + client(sock); + } DBG("Close socket"); close(sock); if(isserver) signals(0); return 0; } +int sendimage(int fd, uint16_t *data, int l){ + if(fd < 1 || !data || l < 1) return TRUE; // empty message + DBG("send new image (size=%d) to fd %d", l, fd); + if(l != send(fd, data, l, MSG_NOSIGNAL)){ + WARN("write()"); + LOGWARN("write()"); + return FALSE; + } + DBG("success"); + if(globlog) LOGDBG("SEND image (size=%d) to fd %d", l, fd); + return TRUE; +} + // simple wrapper over write: add missed newline and log data int sendmessage(int fd, const char *msg, int l){ if(fd < 1 || !msg || l < 1) return TRUE; // empty message @@ -173,7 +197,7 @@ const char *hresult2str(hresult r){ * @return `val` */ char *get_keyval(char *keyval){ - //DBG("Got string %s", keyval); + DBG("Got string %s", keyval); // remove starting spaces in key while(isspace(*keyval)) ++keyval; char *val = strchr(keyval, '='); @@ -181,6 +205,7 @@ char *get_keyval(char *keyval){ *val++ = 0; while(isspace(*val)) ++val; } + DBG("val = %s (%zd bytes)", val, (val)?strlen(val):0); // remove trailing spaces in key char *e = keyval + strlen(keyval) - 1; // last key symbol while(isspace(*e) && e > keyval) --e; diff --git a/socket.h b/socket.h index 51e0201..71c1e8b 100644 --- a/socket.h +++ b/socket.h @@ -17,10 +17,8 @@ */ #pragma once -#ifndef SERSOCK_H__ -#define SERSOCK_H__ - #include +#include // max & min TCP socket port number #define PORTN_MAX (65535) @@ -64,10 +62,9 @@ typedef struct{ } handleritem; int start_socket(int server, char *path, int isnet); +int sendimage(int fd, uint16_t *data, int l); int sendmessage(int fd, const char *msg, int l); int sendstrmessage(int fd, const char *msg); char *get_keyval(char *keyval); int processData(int fd, handleritem *handlers, char *buf, int buflen); - -#endif // SERSOCK_H__