diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d2573c..87f5c13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ set(CMAKE_COLOR_MAKEFILE ON) # cmake -DDEBUG=yes -> debugging if(DEBUG) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Og -g3 -ggdb -Werror") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -ggdb -Werror") add_definitions(-DEBUG) set(CMAKE_BUILD_TYPE DEBUG) set(CMAKE_VERBOSE_MAKEFILE "ON") diff --git a/TOUPCAM_cameras/toupcam.c b/TOUPCAM_cameras/toupcam.c index aa872a2..7fb788a 100644 --- a/TOUPCAM_cameras/toupcam.c +++ b/TOUPCAM_cameras/toupcam.c @@ -31,10 +31,10 @@ extern cc_Wheel wheel; // flags for image processing typedef enum{ + IM_ERROR, IM_SLEEP, IM_STARTED, IM_READY, - IM_ERROR } imstate_t; // devices @@ -63,10 +63,7 @@ static double exptime = 0., starttime = 0.; // return constant string with error code description static const char *errcode(int ecode){ switch(ecode){ -#ifndef STR -#define STR(par) # par -#endif -#define ECASE(code) case code: return STR(code) +#define ECASE(code) case code: return # code ECASE(S_OK); ECASE(S_FALSE); ECASE(E_UNEXPECTED); @@ -131,6 +128,7 @@ static void camclose(){ free(toupcam.data); toupcam.data = NULL; } + toupcam.state = IM_ERROR; } /** @@ -241,7 +239,20 @@ static int campoll(cc_capture_status *st, float *remain){ static void EventCallback(unsigned nEvent, void _U_ *pCallbackCtx){ DBG("CALLBACK with evt %d", nEvent); if(!toupcam.hcam || !toupcam.data){ DBG("NO data!"); return; } - if(nEvent != TOUPCAM_EVENT_IMAGE){ DBG("Not image event"); return; } + switch(nEvent){ + case TOUPCAM_EVENT_DISCONNECTED: + WARNX(_("Camera disconnected")); + camclose(); + return; + case TOUPCAM_EVENT_ERROR: + WARNX(_("Error occured")); + camcancel(); + case TOUPCAM_EVENT_IMAGE: + break; + default: + DBG("Not an image event"); + return; + } ToupcamFrameInfoV4 info = {0}; //DBG("LOCK"); pthread_mutex_lock(&toupcam.mutex); diff --git a/ccdcapture.c b/ccdcapture.c index 17a6a06..1c20e5d 100644 --- a/ccdcapture.c +++ b/ccdcapture.c @@ -49,36 +49,56 @@ static sem_t *sem = SEM_FAILED; // client-side SHM lock int cc_lock_shm(int isserver){ if(sem == SEM_FAILED){ + LOGERR("cc_lock_shm(): can't lock NULL"); DBG("Can't lock NULL"); return FALSE; } - struct timespec ts = {.tv_sec = 0, .tv_nsec = 10000000}; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); // sem_timedwait waits for absolute time! + ts.tv_nsec += 100000000; // 100 ms + if(ts.tv_nsec > 999999999){ + ts.tv_nsec -= 1000000000; + ++ts.tv_sec; + } +#ifdef EBUG + double tstart = sl_dtime(); +#endif DBG("Try to lock"); - if(isserver){ - int locked = TRUE; - while(sem_timedwait(sem, &ts) && locked){ - switch(errno){ - case EINTR: - DBG("Interrupt -> try to lock again"); - break; - default: // timeout or other error -> force locking - DBG("Error locking -> force unlock"); - locked = FALSE; + int locked = TRUE; + while(locked){ + if(0 == sem_timedwait(sem, &ts)){ + locked = FALSE; + break; + } + DBG("Errno=%d (%s)", errno, strerror(errno)); + if(errno == EINTR){ + DBG("Interrupt -> try to lock again"); + }else{ + if(errno == ENOENT || errno == EINVAL){ + DBG("No semaphore -> can't lock"); + LOGERR("cc_lock_shm(): no semaphore -> can't lock"); + return FALSE; } - } - if(locked){ - double t0 = sl_dtime(); - while(sem_trywait(sem) && sl_dtime() - t0 < 0.1) sem_post(sem); // force locking - if(sl_dtime() - t0 >= 0.1) return FALSE; // can't lock - timeout - } - }else{ - if(sem_timedwait(sem, &ts)){ - DBG("Image semaphore is locked too long by other side"); - return FALSE; // can't lock + DBG("Error locking -> %s", (isserver) ? "force unlock" : "exit"); + break; } } - DBG("Semaphore locked"); - return TRUE; + DBG("locked=%d; time=%g", locked, sl_dtime() - tstart); + if(!locked){ + DBG("Semaphore locked"); + return TRUE; + } + if(isserver){ + double t0 = sl_dtime(); + LOGERR("cc_lock_shm(): still locked -> force unlock"); + while(sem_trywait(sem) && sl_dtime() - t0 < 0.1) sem_post(sem); // force locking + if(sl_dtime() - t0 >= 0.1){ + LOGERR("cc_lock_shm(): failed to unlock"); + } + }else{ + DBG("Image semaphore is locked too long by other side"); + } + return FALSE; // can't lock } void cc_unlock_shm(){ @@ -89,10 +109,11 @@ void cc_unlock_shm(){ if(sem_post(sem)){ switch(errno){ case EOVERFLOW: // already unlocked + DBG("Already unlocked"); break; default: // not a valid? or other? - WARN(_("Can't unlock image semaphore")); LOGERR("Can't unlock image semaphore"); + ERR(_("Can't unlock image semaphore (is server alive?)")); return; } } @@ -109,16 +130,21 @@ void cc_init_sem(int isserver){ sem = sem_open(SEM_NAME, 0); } if(sem == SEM_FAILED){ - LOGERR("sem_open failed: %s", strerror(errno)); + WARNX("sem_open() failed: %s", strerror(errno)); + LOGERR("sem_open() failed: %s", strerror(errno)); } } void cc_remove_sem(){ - if(sem == SEM_FAILED) return; - sem_close(sem); + if(sem != SEM_FAILED){ + sem_post(sem); // try to unlock if it was locked + sem_close(sem); + } DBG("semaphore closed\n"); - if(-1 == sem_unlink(SEM_NAME)) + if(-1 == sem_unlink(SEM_NAME)){ LOGERR("Can't delete semaphore"); + WARNX(_("Can't delete semaphore")); + } } /** @@ -175,6 +201,10 @@ int cc_open_socket(int isserver, char *path, int isnet){ WARN("socket()"); continue; } + int bufsz = 33554432; // 32MB for buffer size + setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsz, sizeof(int)); + bufsz = 33554432; + setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(int)); if(isserver){ int reuseaddr = 1; if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ @@ -219,6 +249,10 @@ int cc_senddata(int fd, void *data, size_t l){ while(total < l){ ssize_t sent = send(fd, (char*)data + total, l - total, MSG_NOSIGNAL); if(sent <= 0){ + if(errno == EAGAIN){ + usleep(1000); + continue; + } WARN("send()"); LOGWARN("send()"); break; // error @@ -339,12 +373,8 @@ cc_IMG *cc_getshm(key_t key, size_t imsize){ int shmid = -1; int flags = (imsize) ? IPC_CREAT | 0666 : 0; shmid = shmget(key, 0, flags); - if(shmid < 0 && imsize == 0){ // no SHM segment for client - WARN(_("Can't get shared memory segment %d"), key); - return NULL; - } + struct shmid_ds buf; if(imsize){ // check if segment exists and its size equal to needs - struct shmid_ds buf; if(shmctl(shmid, IPC_STAT, &buf) > -1 && shmsize != buf.shm_segsz){ // remove already existing segment DBG("Need to remove already existing segment"); shmctl(shmid, IPC_RMID, NULL); @@ -355,11 +385,18 @@ cc_IMG *cc_getshm(key_t key, size_t imsize){ return NULL; } }else{ -#ifdef EBUG - struct shmid_ds buf; - if(shmctl(shmid, IPC_STAT, &buf)) WARNX(_("Can't get SHM data")); - else DBG("SHM size = %zd", buf.shm_segsz); -#endif + if(shmid < 0){ // no SHM segment for client + WARN(_("Can't get shared memory segment %d"), key); + return NULL; + } + if(shmctl(shmid, IPC_STAT, &buf)){ + WARNX(_("Can't get SHM data")); + return NULL; + }else DBG("SHM size = %zd", buf.shm_segsz); + if(buf.shm_perm.mode & SHM_DEST){ + WARNX(_("SHM buffer marked for deletion")); + return NULL; + } } flags = (imsize) ? 0 : SHM_RDONLY; // client opens memory in readonly mode cc_IMG *ptr = shmat(shmid, NULL, 0); @@ -368,7 +405,7 @@ cc_IMG *cc_getshm(key_t key, size_t imsize){ return NULL; } if(!imsize){ - if(ptr->MAGICK != CC_SHM_MAGIC){ + if(ptr->MAGICK != CC_SHM_MAGIC || buf.shm_segsz < ptr->bytelen + sizeof(cc_IMG)){ WARNX(_("Shared memory %d isn't belongs to image server"), key); shmdt(ptr); return NULL; @@ -953,3 +990,106 @@ cc_hresult cc_plugin_customcmd(const char *str, cc_parhandler_t *handlers, cc_ch #undef ADDL return result; } + +/** + * @brief cc_newimage - create new empty image + * @param bitpix - 8 or 16 + * @param w - width + * @param h - height + * @return pointer to allocated image or NULL if failed + */ +cc_IMG *cc_newimage(uint8_t bitpix, int w, int h){ + FNAME(); + if(w < 1 || h < 1){ + DBG("Error: w=%d, h=%d", w, h); + return NULL; + } + cc_IMG *newima = calloc(1, sizeof(cc_IMG)); + if(!newima){ + WARN("calloc()"); + return FALSE; + } + int N = bitpix / 8; + if(N < 1 || N > 2){ + DBG("Error: %d bytes per pixel", N); + free(newima); + return NULL; + } + size_t ds = N * w * h; + newima->data = calloc(1, ds); + if(!newima->data){ + WARN("calloc()"); + free(newima); + return NULL; + } + newima->datasize = newima->bytelen = ds; + newima->w = w; + newima->h = h; + newima->MAGICK = CC_SHM_MAGIC; + pthread_mutex_init(&newima->mutex, NULL); + DBG("Created new image %dx%d", w, h); + return newima; +} + +void cc_freeimage(cc_IMG **i){ + if(!i || !*i) return; + cc_IMG *ptr = *i; + free(ptr->data); + free(ptr); + *i = NULL; +} + +/** + * @brief cc_copyimage - copy `src` to `dest` + * @param dest - destination (dest->data would be reallocated if not enough) + * @param src - source image + * @param isshm - ==TRUE if `src` is in shared memory + * @return FALSE if failed + */ +int cc_copyimage(cc_IMG *dest, cc_IMG *src, int isshm){ + FNAME(); + if(!src || !dest || !src->data) return FALSE; + if(src->MAGICK != CC_SHM_MAGIC){ + WARNX(_("Wrong image: bad magick (0x%X instead of 0x%X)"), src->MAGICK, CC_SHM_MAGIC); + return FALSE; + } + if(src->bytelen < 1){ + WARNX(_("Wrong image size")); + return FALSE; + } + DBG("Lock"); + pthread_mutex_lock(&dest->mutex); + if(!dest->data || dest->datasize < src->bytelen){ + size_t newsz = 1024 * (1 + src->bytelen / 1024); + DBG("resize from %zd to %zd bytes", dest->datasize, newsz); + void *nxt = realloc(dest->data, newsz); + if(!nxt){ + LOGERR("realloc() failed"); + WARN("realloc()"); + pthread_mutex_unlock(&dest->mutex); + return FALSE; + } + dest->data = nxt; + dest->datasize = newsz; + DBG("Success"); + } + DBG("Copy fields"); +#define COPY(field) dest->field = src->field; + COPY(timestamp); + COPY(bitpix); + COPY(w); + COPY(h); + COPY(bytelen); + COPY(imnumber); +#undef COPY + DBG("Copy %zd bytes of data", src->bytelen); + void *srcdata = src->data; + if(isshm){ + srcdata = (void*)((uint8_t*)src + sizeof(cc_IMG)); + DBG("Copy from SHM by offset; srcptr: %p; datastart: %p, offset: %zd", src, srcdata, sizeof(cc_IMG)); + } + memcpy(dest->data, srcdata, src->bytelen); + DBG("All OK"); + pthread_mutex_unlock(&dest->mutex); + return TRUE; +} diff --git a/ccdcapture.h b/ccdcapture.h index d5c44ad..3eb6f6a 100644 --- a/ccdcapture.h +++ b/ccdcapture.h @@ -34,20 +34,22 @@ #define SEM_NAME "ccdcapture" // base image parameters - sent by socket and stored in shared memory -typedef struct __attribute__((packed)){ +typedef struct{ // __attribute__((packed)) uint32_t MAGICK; // magick (DEADBEEF) - to mark our shm + pthread_mutex_t mutex; // mutex for working with image data double timestamp; // timestamp of image taken - uint8_t bitpix; // bits per pixel (8 or 16) int w, h; // image size int gotstat; // stat counted + size_t bytelen; // size of image in bytes + size_t datasize; // size of `data` buffer + size_t imnumber; // counter of images captured from server's start + uint8_t bitpix; // bits per pixel (8 or 16) uint16_t max, min; // min/max values float avr, std; // statistics - size_t bytelen; // size of image in bytes - size_t imnumber; // counter of images captured from server's start - void *data; // pointer to data (next byte after this struct) - only for server - /* `data` is uint8_t or uint16_t depending on `bitpix` */ - char fitsheader[FITS_HEADER_STRINGS_MAX][FLEN_CARD]; // FITS-header for given image size_t headerstrings; // amount of records in header + /* `data` is uint8_t or uint16_t depending on `bitpix` */ + void *data; // pointer to data (next byte after this struct) - only for server + char fitsheader[FITS_HEADER_STRINGS_MAX][FLEN_CARD]; // FITS-header for given image } cc_IMG; typedef struct{ @@ -323,6 +325,10 @@ void cc_charbufaddline(cc_charbuff *b, const char *s); cc_strbuff *cc_strbufnew(size_t size, size_t stringsize); void cc_strbufdel(cc_strbuff **buf); +cc_IMG *cc_newimage(uint8_t bitpix, int w, int h); +int cc_copyimage(cc_IMG *dest, cc_IMG *src, int isshm); +void cc_freeimage(cc_IMG **i); + const char *cc_hresult2str(cc_hresult r); cc_hresult cc_str2hresult(const char *str); int cc_setNtries(int n); diff --git a/ccdfunc.c b/ccdfunc.c index bfba9bb..329eeaa 100644 --- a/ccdfunc.c +++ b/ccdfunc.c @@ -196,6 +196,7 @@ do{ int status = 0, kt = 0; \ // return FALSE if failed int saveFITS(cc_IMG *img, char **outp){ int ret = FALSE; + if(!img || !img->data || !outp) return FALSE; char fnam[PATH_MAX+1]; if(!GP->outfile && !GP->outfileprefix){ LOGWARN("Image not saved: neither filename nor filename prefix pointed"); @@ -221,6 +222,7 @@ int saveFITS(cc_IMG *img, char **outp){ LOGERR("Can't save image with prefix %s", GP->outfileprefix); } } + pthread_mutex_lock(&img->mutex); int width = img->w, height = img->h; long naxes[2] = {width, height}; struct tm *tm_time; @@ -275,6 +277,7 @@ fits_write_history(fp, bufhdr->buf, &s); if(fitserror) goto cloerr; TRYFITS(fits_close_file, fp); cloerr: + pthread_mutex_unlock(&img->mutex); if(fitserror == 0){ LOGMSG("Save file '%s'", fnam); verbose(VERBOSE_PRIMARY, _("File saved as '%s'"), fnam); @@ -839,17 +842,16 @@ static volatile int exitgrab = FALSE; static volatile size_t lastgrabno = 0; static void *grabnext(void *arg){ FNAME(); - cc_IMG *ima = (cc_IMG*) arg; + if(!arg) return NULL; + cc_IMG *ima = (cc_IMG*)arg; do{ if(exitgrab) return NULL; TIMESTAMP("Start next exp"); TIMEINIT(); - if(!ima || !camera) return NULL; + if(!camera) return NULL; if(!camera->startexposition) ERRX(_("Camera plugin have no function `start exposition`")); if(!camera->startexposition()){ - WARNX(_("Can't start exposition")); - usleep(10000); - continue; + ERRX(_("Can't start exposition")); } cc_capture_status cs = CAPTURE_ABORTED; TIMESTAMP("Poll"); @@ -866,6 +868,7 @@ static void *grabnext(void *arg){ //calculate_stat(ima); TIMESTAMP("OK"); }while(1); + return NULL; } @@ -875,7 +878,7 @@ static void *grabnext(void *arg){ * @param img - pointer to cc_IMG* (if cc_IMG* is NULL, will be allocated here) * @return TRUE if new image available */ -int ccdcaptured(cc_IMG **imgptr){ +int ccdcaptured(cc_IMG *imgptr){ if(!imgptr) return FALSE; //TIMESTAMP("ccdcaptured() start"); static pthread_t grabthread = 0; @@ -891,32 +894,21 @@ int ccdcaptured(cc_IMG **imgptr){ DBG("OK"); return FALSE; } - cc_frameformat fmt = camera->geometry; - int raw_width = fmt.w / GP->hbin, raw_height = fmt.h / GP->vbin; - cc_IMG *ima = NULL; - if(*imgptr && ((*imgptr)->w != raw_width || (*imgptr)->h != raw_height)) FREE(*imgptr); - if(!*imgptr){ - uint16_t *img = MALLOC(uint16_t, raw_width * raw_height); - DBG("\n\nAllocated image 2x%dx%d=%d", raw_width, raw_height, 2 * raw_width * raw_height); - ima = MALLOC(cc_IMG, 1); - ima->data = img; - ima->w = raw_width; - ima->h = raw_height; - *imgptr = ima; - }else ima = *imgptr; + //cc_frameformat fmt = camera->geometry; + //int raw_width = fmt.w / GP->hbin, raw_height = fmt.h / GP->vbin; if(!grabthread){ // start new grab TIMESTAMP("Start new grab"); TIMEINIT(); - if(pthread_create(&grabthread, NULL, &grabnext, (void*)ima)){ + if(pthread_create(&grabthread, NULL, &grabnext, (void*)imgptr)){ WARN(_("Can't create grabbing thread")); grabthread = 0; } }else{ // grab in process - if(ima->imnumber != lastgrabno){ // done + if(imgptr->imnumber != lastgrabno){ // done /*ssize_t delta = ima->imnumber - lastgrabno; if(delta > 0 && delta != 1) WARNX("ccdcaptured(): missed %zd images", delta-1);*/ - lastgrabno = ima->imnumber; + lastgrabno = imgptr->imnumber; TIMESTAMP("Got exp #%zd", lastgrabno); framerate(); return TRUE; @@ -963,9 +955,6 @@ int start_socket(int isserver){ } DBG("Close socket"); close(sock); - if(isserver){ - close(imsock); - signals(0); - } + if(isserver) close(imsock); return 0; } diff --git a/ccdfunc.h b/ccdfunc.h index 47a7919..971a136 100644 --- a/ccdfunc.h +++ b/ccdfunc.h @@ -40,7 +40,7 @@ void closewheel(); void closecam(); #ifdef IMAGEVIEW void framerate(); -int ccdcaptured(cc_IMG **img); +int ccdcaptured(cc_IMG *img); #endif int start_socket(int isserver); diff --git a/client.c b/client.c index a0978db..afd4666 100644 --- a/client.c +++ b/client.c @@ -51,9 +51,7 @@ static int xc0,yc0,xc1,yc1; // current format static volatile atomic_int grabno = 0; static int oldgrabno = 0; // IPC key for shared memory -static cc_IMG ima = {0}, *shmima = NULL; // ima - local storage, shmima - shm (if available) -static size_t imbufsz = 0; // image buffer for allocated `ima` -static uint8_t *imbuf = NULL; // we can't use shmima->data as it belongs to server, so we use `imbuf` and set ima.data = imbuf +static cc_IMG *locima = NULL, *shmima = NULL; // ima - local storage, shmima - shm (if available) static volatile atomic_int current_image_number = -1; // for net-parser - last number of exposed image #if 0 @@ -82,7 +80,7 @@ static char *readmsg(int fd){ #endif #define CMP_ANS(cmd, ans) strncmp(cmd, ans, sizeof(cmd)-1) -// parser of CCD server messages; return TRUE to exit from polling cycle of `getans` (if receive 'FAIL', 'OK' or 'BUSY') +// parser of CCD server messages; return parsing result static cc_hresult parseans(char *ans){ if(!ans) return CC_RESULT_BADKEY; //TIMESTAMP("parseans() begin"); @@ -97,18 +95,17 @@ static cc_hresult parseans(char *ans){ } char *val = cc_get_keyval(&ans); // now `ans` is a key and `val` its value if(0 == CMP_ANS(CC_CMD_EXPSTATE, ans)){ - int st = atoi(val); - atomic_store(&expstate, st); - DBG("Current state: %d", atomic_load(&expstate)); - return CC_RESULT_SILENCE; + int st = atoi(val), oldst = atomic_load(&expstate); + if(oldst != CAMERA_FRAMERDY){ + atomic_store(&expstate, st); + DBG("Current state: %d", atomic_load(&expstate)); + } }else if(0 == CMP_ANS(CC_CMD_FRAMEMAX, ans)){ sscanf(val, "%d,%d,%d,%d", &xm0, &ym0, &xm1, &ym1); DBG("Got maxformat: %d,%d,%d,%d", xm0, ym0, xm1, ym1); - return CC_RESULT_SILENCE; }else if(0 == CMP_ANS(CC_CMD_FRAMEFORMAT, ans)){ sscanf(val, "%d,%d,%d,%d", &xc0, &yc0, &xc1, &yc1); DBG("Got current format: %d,%d,%d,%d", xc0, yc0, xc1, yc1); - return CC_RESULT_SILENCE; }else if(0 == CMP_ANS(CC_CMD_IMNUMBER, ans)){ atomic_store(¤t_image_number, atoi(val)); } @@ -120,46 +117,62 @@ static cc_hresult parseans(char *ans){ // if msg != NULL - wait for it in answer static int getans(int sock, const char *msg){ double t0 = sl_dtime(); - char buf[BUFSIZ+1]; - int idx = 0; - char *ans = NULL; + static sl_ringbuffer_t *RB = NULL; + if(!RB){ + RB = sl_RB_new(BUFSIZ); + if(!RB){ + WARNX(_("Can't allocate buffer")); + return FALSE; + } + } TIMESTAMP("GetAns(%s)", msg); double tmout = answer_timeout + 5.; // make first timeout larger for slow networks // TODO: increase first timeout up to 15-30s (add key?) cc_hresult res = CC_RESULT_FAIL; + char buf[256]; while(sl_dtime() - t0 < tmout){ - ans = NULL; if(1 == sl_canread(sock)){ - ssize_t got = read(sock, buf+idx, BUFSIZ-idx); + ssize_t got = read(sock, buf, 255); if(got > 0){ - idx += got; - buf[idx] = 0; - char *nl = strchr(buf, '\n'); - if(nl){ - *nl = 0; - ans = buf; - DBG("got '%s'", ans); + DBG("Got %zd bytes (%s)", got, buf); + if(got != (ssize_t)sl_RB_write(RB, (uint8_t*)buf, got)){ + WARNX("Ringbuffer overflow??"); + sl_RB_clearbuf(RB); + return FALSE; } + }else if(got < 0){ + DBG("ERR: got=%zd", got); + if(errno == EAGAIN){ + usleep(1000); + continue; + } + WARNX(_("Server disconnected?")); + LOGWARN("Server disconnected?"); + return FALSE; } } - if(!ans) continue; + if(sl_RB_hasbyte(RB, '\n') < 0) continue; + DBG("Got newline in RB"); + if(sl_RB_readline(RB, buf, 255) < 1){ + WARNX(_("Got empty string")); + continue; + } // got answer -> make timeout less tmout = answer_timeout; t0 = sl_dtime(); - TIMESTAMP("Got from server: %s", ans); - verbose(VERBOSE_PRIMARY, "\t%s", ans); - DBG("1 msg-> %s, ans -> %s", msg, ans); - res = parseans(ans); - DBG("2 msg-> %s, ans -> %s; result: %d", msg, ans, res); + TIMESTAMP("Got from server: %s", buf); + verbose(VERBOSE_PRIMARY, "\t%s", buf); + DBG("1 msg-> %s, ans -> %s", msg, buf); + res = parseans(buf); + DBG("2 msg-> %s, ans -> %s; result: %d", msg, buf, res); if(msg){ - if(res != CC_RESULT_SILENCE || strncmp(ans, msg, strlen(msg))) continue; + if(res != CC_RESULT_SILENCE || strncmp(buf, msg, strlen(msg))) continue; else res = CC_RESULT_OK; } DBG("Got answer -> break"); break; } - TIMESTAMP("GetAns(%s), ans: '%s', result: %d", msg, ans, res); - if(!ans) DBG("Got no answer from server; result=%d", res); + TIMESTAMP("GetAns(%s), result: %d", msg, res); if(res == CC_RESULT_OK) return TRUE; return FALSE; } @@ -269,7 +282,6 @@ static int readNbytes(int fd, size_t N, uint8_t *buf){ size_t got = 0, need = N; double t0 = sl_dtime(); while(sl_dtime() - t0 < CC_CLIENT_TIMEOUT /*&& sl_canread(fd)*/ && need){ - t0 = sl_dtime(); ssize_t rd = read(fd, buf + got, need); if(rd <= 0){ if(errno == EAGAIN || errno == EWOULDBLOCK) continue; @@ -277,11 +289,119 @@ static int readNbytes(int fd, size_t N, uint8_t *buf){ signals(1); } got += rd; need -= rd; + t0 = sl_dtime(); } if(need) return FALSE; // didn't got whole packet return TRUE; } +static int refresh_shm(){ + if(!shmima){ + shmima = cc_getshm(GP->shmkey, 0); // try to init client shm + if(shmima){ + cc_init_sem(FALSE); + DBG("Got access to shared memory"); + return TRUE; + } + return FALSE; + } + int shmid = shmget(GP->shmkey, 0, 0); + if(shmid < 0){ + // Segment was deleted + shmdt(shmima); + shmima = NULL; + // refresh connection + return refresh_shm(); + } + struct shmid_ds buf; + if(shmctl(shmid, IPC_STAT, &buf) == 0){ + if(buf.shm_perm.mode & SHM_DEST){ // marked for deletion + shmdt(shmima); + shmima = NULL; + return refresh_shm(); + } + // valid segment + return TRUE; + } + return FALSE; +} + +static int lockshm(){ + int locked = FALSE; + double t0 = sl_dtime(); + while(sl_dtime() - t0 < MUTEX_LOCK_TMOUT){ + if(cc_lock_shm(FALSE)){ + DBG("Locked"); + locked = TRUE; + break; + } + usleep(100); + } + if(!locked) WARNX(_("Can't lock shared memory")); + return locked; +} + +static int getshmimage(int *shmlocked){ + if(!shmlocked || !shmima) return FALSE; + if(!refresh_shm()) return FALSE; + if(!*shmlocked && !(*shmlocked = lockshm())) return FALSE; + DBG("Server's imno: %zd, bytelen: %zd", shmima->imnumber, shmima->bytelen); + int ret = cc_copyimage(locima, shmima, TRUE); + TIMESTAMP("Got by shared memory"); + return ret; +} + +static int getsocksizes(int *imsock){ + if(!imsock || *imsock > -1) return FALSE; + DBG("Open socket @ %s", GP->imageport); + *imsock = cc_open_socket(FALSE, GP->imageport, TRUE); + if(*imsock < 0){ + WARNX(_("Can't open image transport socket")); + return FALSE; + } + // get image size + cc_IMG ima; + if(!readNbytes(*imsock, sizeof(cc_IMG), (uint8_t*)&ima)){ + WARNX(_("Can't read image header over socket")); + return FALSE; + } + if(ima.MAGICK != CC_SHM_MAGIC || ima.bytelen < 1) return FALSE; + // now copy fields +#define COPY(field) locima->field = ima.field; + COPY(timestamp); + COPY(bitpix); + COPY(w); + COPY(h); + COPY(bytelen); + COPY(imnumber); +#undef COPY + return TRUE; +} + +static int getsockimage(int *imsock){ + if(!imsock || *imsock < 0) return FALSE; + pthread_mutex_lock(&locima->mutex); + if(locima->datasize < locima->bytelen){ + size_t newsz = 1024 * (1 + locima->bytelen / 1024); + void *nxt = realloc(locima->data, newsz); + if(!nxt){ + LOGERR("realloc() failed"); + WARN("realloc()"); + pthread_mutex_unlock(&locima->mutex); + return FALSE; + } + locima->data = nxt; + } + int ok = readNbytes(*imsock, locima->bytelen, locima->data); + pthread_mutex_unlock(&locima->mutex); + if(!ok){ + WARNX(_("Can't read image data")); + return FALSE; + } + TIMESTAMP("Got by socket"); + return TRUE; +} + /** * @brief getimage - read image from shared memory or socket * @param askheader == TRUE for storing FITS-header @@ -291,132 +411,85 @@ static int getimage(int askheader){ FNAME(); int imsock = -1, shmlocked = FALSE, ret = FALSE; static double oldtimestamp = -1.; - TIMESTAMP("Get image sizes"); - if(shmima){ // read image from shared memory - DBG("Try to read from SHM"); - double t0 = sl_dtime(); - while(sl_dtime() - t0 < MUTEX_LOCK_TMOUT){ - if(cc_lock_shm(FALSE)){ - DBG("Locked"); - shmlocked = TRUE; - break; - } - usleep(100); - } - if(!shmlocked){ - WARNX(_("Can't lock shared memory")); - return FALSE; - } - memcpy(&ima, shmima, sizeof(cc_IMG)); - }else{ // get image by socket - if(imsock < 0){ - DBG("Open socket @ %s", GP->imageport); - imsock = cc_open_socket(FALSE, GP->imageport, TRUE); - } - if(imsock < 0) ERRX(_("getimage(): can't open image transport socket")); - // get image size - if(!readNbytes(imsock, sizeof(cc_IMG), (uint8_t*)&ima)){ - WARNX(_("Can't read image header")); - goto eofg; + TIMESTAMP("Get image sizes (or full image over SHM)"); + if(!locima){ + locima = cc_newimage(16, 1024, 1024); + if(!locima){ + WARN("calloc()"); return FALSE; } } - if(ima.MAGICK != CC_SHM_MAGIC){ - WARNX(_("Wrong image: bad magick")); - goto eofg; - } - if(ima.bytelen < 1){ - WARNX(_("Wrong image size")); - goto eofg; - } - DBG("bytelen=%zd, w=%d, h=%d; bitpix=%d", ima.bytelen, ima.w, ima.h, ima.bitpix); - // realloc memory if needed - if(imbufsz < ima.bytelen){ - size_t newsz = 1024 * (1 + ima.bytelen / 1024); - DBG("Reallocate memory from %zd to %zd", imbufsz, newsz); - uint8_t *b = imbuf; - imbuf = realloc(imbuf, imbufsz); - if(imbuf){ - imbufsz = newsz; - DBG("Size after realloc: %zd", imbufsz); - }else{ - WARNX(_("Can't reallocate memory for image buffer")); - imbuf = b; - goto eofg; - } - } - ima.data = imbuf; // renew this value each time after getting `ima` from server - TIMESTAMP("Start of data read"); - if(shmima){ - uint8_t *datastart = ((uint8_t*)shmima) + sizeof(cc_IMG); - DBG("first image byte: %d; bytelen: %zd", *datastart, ima.bytelen); - memcpy(imbuf, datastart, ima.bytelen); - TIMESTAMP("Got by shared memory"); - if(!askheader){ - cc_unlock_shm(); - shmlocked = FALSE; - } - ret = TRUE; - }else{ - if(!readNbytes(imsock, ima.bytelen, imbuf)){ + ret = getshmimage(&shmlocked); + if(!ret){ // can't get by shm -> try over NET + DBG("Try to get image over network"); + if(!getsocksizes(&imsock)) goto eofg; + TIMESTAMP("Start of data read"); + ret = getsockimage(&imsock); + if(!ret){ WARNX(_("Can't read image data")); goto eofg; } - ret = TRUE; - TIMESTAMP("Got by socket"); } - DBG("timestamps new-old=%g; imno: %zd", ima.timestamp - oldtimestamp, ima.imnumber); - if(ima.timestamp != oldtimestamp){ // test if image is really new - oldtimestamp = ima.timestamp; - atomic_store(&grabno, ima.imnumber); - TIMESTAMP("Got image #%zd", ima.imnumber); + DBG("timestamps new-old=%g; imno: %zd", locima->timestamp - oldtimestamp, locima->imnumber); + if(locima->timestamp != oldtimestamp){ // test if image is really new + oldtimestamp = locima->timestamp; + atomic_store(&grabno, locima->imnumber); + TIMESTAMP("Got image #%zd", locima->imnumber); if(askheader){ // read FITS-header for later saving if(shmima){ - size_t rsz = FLEN_CARD * ima.headerstrings; - memcpy(ima.fitsheader, shmima->fitsheader, rsz); + if(locima->headerstrings > FITS_HEADER_STRINGS_MAX){ + WARNX(_("Too many FITS headers, truncating")); + locima->headerstrings = FITS_HEADER_STRINGS_MAX; + } + size_t rsz = FLEN_CARD * locima->headerstrings; + memcpy(locima->fitsheader, shmima->fitsheader, rsz); + cc_unlock_shm(); + shmlocked = FALSE; }else{ uint8_t card[FLEN_CARD]; - for(size_t i = 0; i < ima.headerstrings; ++i){ + for(size_t i = 0; i < locima->headerstrings; ++i){ if(!readNbytes(imsock, FLEN_CARD, card)){ - WARNX(_("Can't read full header, got %zd records from %zd"), i, ima.headerstrings); + WARNX(_("Can't read full header, got %zd records from %zd"), i, locima->headerstrings); break; } - memcpy(&ima.fitsheader[i], card, FLEN_CARD); + memcpy(&locima->fitsheader[i], card, FLEN_CARD); } + close(imsock); + imsock = -1; } if(GP->addhdr){ // add records from client-side files char **nxtfile = GP->addhdr; while(*nxtfile){ - cc_kwfromfile(&ima, *(nxtfile++)); + cc_kwfromfile(locima, *(nxtfile++)); } } - }else ima.headerstrings = 0; - }else WARNX("Still got old image"); + }else locima->headerstrings = 0; + }else WARNX(_("Still got old image")); eofg: - if(imsock != -1) close(imsock); // reopen in next time in case of error + if(imsock > -1) close(imsock); // reopen in next time in case of error if(shmlocked) cc_unlock_shm(); return ret; } -// get number of current image; return number or -1 if got error/timeout +// get number of current image static int curImNo(int sock){ + int N = -1; if(shmima){ - if(!cc_lock_shm(FALSE)) return -1; - int CurNo = shmima->imnumber; - cc_unlock_shm(); - return CurNo; + if(lockshm()){ + N = shmima->imnumber; + cc_unlock_shm(); + atomic_store(¤t_image_number, N); + } } - // no shared memory: try to get number over TCP - SENDCMDW(CC_CMD_IMNUMBER); - return atomic_load(¤t_image_number); + if(N < 0){ // no shared memory: try to get number over TCP + SENDCMDW(CC_CMD_IMNUMBER); + N = atomic_load(¤t_image_number); + } + return N; } void client(int sock){ if(sock < 0) ERRX(_("Can't run without command socket")); - if(!GP->forceimsock && !shmima){ // init shm buffer if user don't ask to force workign through image socket - shmima = cc_getshm(GP->shmkey, 0); // try to init client shm - if(shmima) cc_init_sem(FALSE); - DBG("Got access to shared memory: %s", shmima ? "OK" : "FAIL"); - } + if(!GP->forceimsock) refresh_shm(); // init shm buffer if user don't ask to force workign through image socket if(GP->restart){ SENDCMDW(CC_CMD_RESTART); return; @@ -426,6 +499,7 @@ void client(int sock){ TIMESTAMP("Got headers"); double t0 = sl_dtime(), tw, tstart; int Nremain = 0, nframe = 1; + atomic_store(&expstate, CAMERA_IDLE); // could be changed earlier // if client gives filename/prefix or Nframes, make exposition if((GP->outfile && *GP->outfile) || (GP->outfileprefix && *GP->outfileprefix) || GP->nframes > 0){ Nremain = GP->nframes; @@ -434,7 +508,6 @@ void client(int sock){ } else return; // just send headers and exit double timeout = CC_CLIENT_TIMEOUT; verbose(VERBOSE_PRIMARY, _("Exposing frame 1...")); - atomic_store(&expstate, CAMERA_CAPTURE); // could be changed earlier DBG("Current state: %d", atomic_load(&expstate)); verbose(VERBOSE_PRIMARY, _("Wait for exposition end")); t0 = sl_dtime(); @@ -443,6 +516,7 @@ void client(int sock){ while(sl_dtime() - t0 < timeout){ if(sl_dtime() - tw > CC_WAIT_TIMEOUT){ SENDCMDW(CC_CMD_TREMAIN); // get remained time + SENDCMDW(CC_CMD_EXPSTATE); tw = sl_dtime(); usleep(100000); } @@ -450,9 +524,6 @@ void client(int sock){ t0 = sl_dtime(); // refresh timeout until exp not ends usleep(1000); continue; - }else{ - SENDCMDW(CC_CMD_EXPSTATE); - usleep(1000); } int curst = atomic_load(&expstate); DBG("Current state: %d", curst); @@ -465,23 +536,23 @@ void client(int sock){ } continue; } - if(curst == CAMERA_FRAMERDY){ + int cur = curImNo(sock); + if(curst == CAMERA_FRAMERDY || cur != lastImNo){ atomic_store(&expstate, CAMERA_IDLE); - int cur = curImNo(sock); - DBG("Current state: %d, imno: %d", atomic_load(&expstate), cur); + DBG("Current imno: %d", cur); if(Nremain > 1){ // start next capture verbose(VERBOSE_PRIMARY, _("Exposing frame %d..."), nframe); SENDMSGW(CC_CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); tstart = sl_dtime(); } int failed = TRUE; - if(lastImNo < cur){ + if(lastImNo != cur){ lastImNo = cur; verbose(VERBOSE_SECONDARY, _("Frame ready, try to grab")); if(!getimage(TRUE)){ WARNX(_("Can't get next image")); }else{ - if(saveFITS(&ima, &lastfilename)){ + if(saveFITS(locima, &lastfilename)){ --Nremain; ++nframe; failed = FALSE; @@ -534,9 +605,8 @@ static void *grabnext(void _U_ *arg){ int lastImNo = curImNo(sock); while(1){ if(!getWin()) exit(1); - TIMESTAMP("End of cycle, start new"); - atomic_store(&expstate, CAMERA_CAPTURE); - DBG("Current state: %d", atomic_load(&expstate)); + TIMESTAMP("Start of capturing cycle"); + atomic_store(&expstate, CAMERA_IDLE); TIMEINIT(); SENDMSGW(CC_CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); // start capture double timeout = GP->exptime + CC_CLIENT_TIMEOUT, t0 = sl_dtime(); @@ -547,24 +617,29 @@ static void *grabnext(void _U_ *arg){ } TIMESTAMP("Wait for exposition ends (%g s), sleep for %dus", timeout, sleept); int curst = CAMERA_CAPTURE; + int cur = lastImNo; + SENDCMDW(CC_CMD_EXPSTATE); while(sl_dtime() - t0 < timeout){ DBG("start sleep for %dus", sleept); usleep(sleept); - SENDCMDW(CC_CMD_EXPSTATE); + cur = curImNo(sock); curst = atomic_load(&expstate); - if(curst != CAMERA_CAPTURE) break; + if(curst != CAMERA_CAPTURE || cur != lastImNo) break; if(sl_dtime() - t0 > GP->exptime && sleept != CC_IMWAIT_SLEEP){ - DBG("Set sleeping time to %dus", sleept); sleept = CC_IMWAIT_SLEEP; + DBG("Set sleeping time to %dus", sleept); + SENDCMDW(CC_CMD_EXPSTATE); } } - int cur = curImNo(sock); - if(sl_dtime() - t0 >= timeout || curst != CAMERA_FRAMERDY || cur <= lastImNo){ + SENDCMDW(CC_CMD_EXPSTATE); + curst = atomic_load(&expstate); + if(curst == CAMERA_ERROR) ERRX(_("Camera in error state")); + if(sl_dtime() - t0 >= timeout && cur != lastImNo){ WARNX(_("Image wasn't received, state: %d, waiting: %g, lastNo: %d, curNo: %d (timeout: %g)"), curst, sl_dtime() - t0, lastImNo, cur, timeout); continue; } lastImNo = cur; - TIMESTAMP("Frame ready (%d from server's start)", cur); + TIMESTAMP("Frame ready (%d from start)", cur); getimage(FALSE); } return NULL; @@ -585,7 +660,7 @@ static void *waitimage(void _U_ *arg){ t0 = tcur; } int cur = curImNo(sock); - if(cur <= lastImNo){ + if(cur == lastImNo){ usleep(CC_IMWAIT_SLEEP); continue; } @@ -600,7 +675,7 @@ static void *waitimage(void _U_ *arg){ } // try to capture images for viewer -int sockcaptured(cc_IMG **imgptr){ +int sockcaptured(cc_IMG *imgptr){ //TIMESTAMP("sockcaptured() start"); if(!imgptr) return FALSE; static pthread_t grabthread = 0; @@ -634,13 +709,12 @@ int sockcaptured(cc_IMG **imgptr){ }else{ // grab in process int curno = atomic_load(&grabno); if(curno != oldgrabno){ // image is ready - TIMESTAMP("Image #%d ready", curno); - if(*imgptr && (*imgptr != &ima)) free(*imgptr); - *imgptr = &ima; + TIMESTAMP("Image #%d ready (old was %d)", curno, oldgrabno); oldgrabno = curno; framerate(); //TIMESTAMP("sockcaptured() end, return TRUE"); - return TRUE; + int ret = cc_copyimage(imgptr, locima, FALSE); + return ret; } } //TIMESTAMP("sockcaptured() end, return FALSE"); diff --git a/client.h b/client.h index eae3790..eb2766c 100644 --- a/client.h +++ b/client.h @@ -24,5 +24,5 @@ void client(int fd); #ifdef IMAGEVIEW void init_grab_sock(int sock); -int sockcaptured(cc_IMG **img); +int sockcaptured(cc_IMG *img); #endif diff --git a/imageview.c b/imageview.c index e54ca3f..8f67f28 100644 --- a/imageview.c +++ b/imageview.c @@ -288,13 +288,15 @@ static void createGLwin(char *title, int w, int h, rawimage *rawdata){ if(!initialized) imageview_init(); if(win) killwindow(); win = MALLOC(windowData, 1); + int wh = w * h; + win->rawdata = MALLOC(uint8_t, wh); rawimage *raw; if(rawdata){ raw = rawdata; }else{ raw = MALLOC(rawimage, 1); if(raw){ - raw->rawdata = MALLOC(GLubyte, w*h*3); + raw->rawdata = MALLOC(GLubyte, wh*3); raw->w = w; raw->h = h; raw->changed = 1; @@ -445,15 +447,12 @@ result: 0.0014689s /** * @brief equalize - hystogram equalization - * @param ori (io) - input/output data - * @param w,h - image width and height - * @return data allocated here + * @param img (i) - input image */ -static uint8_t *equalize(cc_IMG *img, int w, int h){ - uint8_t *retn = MALLOC(uint8_t, w*h); +static void equalize(cc_IMG *img){ double orig_hysto[0x10000] = {0.}; // original hystogram uint8_t eq_levls[0x10000] = {0}; // levels to convert: newpix = eq_levls[oldpix] - int s = w*h; + int s = img->h * img->w; //double t0 = dtime(); /* -- takes too long because of sync #pragma omp parallel @@ -492,6 +491,7 @@ static uint8_t *equalize(cc_IMG *img, int w, int h){ } //WARNX("equal: %gs", dtime()-t0); //OMP_FOR() -- takes the same time! + uint8_t *retn = win->rawdata; if(bytes == 1){ uint8_t *data = (uint8_t*) img->data; for(int i = 0; i < s; ++i){ @@ -504,7 +504,6 @@ static uint8_t *equalize(cc_IMG *img, int w, int h){ } } //WARNX("result: %gs", dtime()-t0); - return retn; } /* no omp @ histo: @@ -518,10 +517,9 @@ cuts: 0.00188208s */ // count image cuts as [median-sigma median+5sigma] -static uint8_t *mkcuts(cc_IMG *img, int w, int h){ - uint8_t *retn = MALLOC(uint8_t, w*h); +static void mkcuts(cc_IMG *img){ int orig_hysto[0x10000] = {0.}; // original hystogram - int s = w*h; + int s = img->h * img->w; double sum = 0., sum2 = 0.; int bytes = cc_getNbytes(img); TIMESTAMP("Make histogram"); @@ -584,9 +582,11 @@ static uint8_t *mkcuts(cc_IMG *img, int w, int h){ //WARNX("stat: %gs", dtime()-t0); // DEBUG: 2ms without OMP; 0.7ms with TIMESTAMP("apply cuts"); + uint8_t *retn = win->rawdata; if(bytes == 1){ + DBG("8 bit data"); uint8_t *data = (uint8_t*) img->data; - OMP_FOR() + //OMP_FOR() for(int i = 0; i < s; ++i){ uint16_t old = data[i]; if(old > high){ retn[i] = 255; continue; } @@ -594,8 +594,9 @@ static uint8_t *mkcuts(cc_IMG *img, int w, int h){ retn[i] = (uint8_t)(A*(old - low)); } }else{ + DBG("16 bit data"); uint16_t *data = (uint16_t*) img->data; - OMP_FOR() + //OMP_FOR() for(int i = 0; i < s; ++i){ uint16_t old = data[i]; if(old > high){ retn[i] = 255; continue; } @@ -603,8 +604,8 @@ static uint8_t *mkcuts(cc_IMG *img, int w, int h){ retn[i] = (uint8_t)(A*(old - low)); } } + DBG("Done"); //WARNX("cuts: %gs", dtime()-t0); - return retn; } static void change_displayed_image(cc_IMG *img){ @@ -614,29 +615,43 @@ static void change_displayed_image(cc_IMG *img){ TIMESTAMP("Got image #%zd", img->imnumber); if(delta > 0 && delta != 1) WARNX(_("Missed %zd images"), delta-1); lastN = img->imnumber; - //pthread_mutex_lock(&win->mutex); - rawimage *im = win->image; - DBG("imh=%d, imw=%d, ch=%u, cw=%u", im->h, im->w, img->h, img->w); + pthread_mutex_lock(&win->mutex); int w = img->w, h = img->h, s = w*h; - if(!im || (im->h != h) || (im->w != w)){ // realloc image to new size - pthread_mutex_lock(&win->mutex); + if(!win->image || ! win->rawdata || (win->image->h != h) || (win->image->w != w)){ // realloc image & raw image to new size + //pthread_mutex_lock(&win->mutex); DBG("\n\nRealloc rawdata"); - if(!im) im = MALLOC(rawimage, 1); - if(im->h*im->w < s) im->rawdata = realloc(im->rawdata, s*3); - im->h = h; im->w = w; - win->image = im; + uint8_t *raw = win->image->rawdata; + win->image->rawdata = realloc(win->image->rawdata, s*3); + if(!win->image->rawdata){ + WARN("realloc()"); + LOGERR("Realloc() error"); + win->image->rawdata = raw; + return; + } + win->image->h = h; win->image->w = w; + raw = win->rawdata; + win->rawdata = realloc(win->rawdata, s); + if(!win->rawdata){ + WARN("realloc()"); + LOGERR("Realloc() error"); + win->rawdata = raw; + return; + } DBG("win->image changed"); - pthread_mutex_unlock(&win->mutex); + //pthread_mutex_unlock(&win->mutex); } + rawimage *im = win->image; + uint8_t *raw = win->rawdata; + DBG("imh=%d, imw=%d, ch=%u, cw=%u", im->h, im->w, img->h, img->w); TIMESTAMP("level correction"); - uint8_t *newima; if(imequalize){ DBG("equalize"); - newima = equalize(img, w, h); + equalize(img); }else{ DBG("cuts"); - newima = mkcuts(img, w, h); + mkcuts(img); } + //pthread_mutex_lock(&win->mutex); GLubyte *dst = im->rawdata; TIMESTAMP("colorfun"); //double t0 = dtime(); @@ -645,17 +660,16 @@ static void change_displayed_image(cc_IMG *img){ OMP_FOR() for(int i = 0; i < s; ++i){ GLubyte *t = &dst[i*3]; - t[0] = t[1] = t[2] = colorfun(newima[i]); + t[0] = t[1] = t[2] = colorfun(raw[i]); } }else{ // without OMP: 3.6ms; with OMP: 1.7ms OMP_FOR() for(int i = 0; i < s; ++i){ - gray2rgb(colorfun(newima[i] / 256.), &dst[i*3]); + gray2rgb(colorfun(raw[i] / 256.), &dst[i*3]); } } //WARNX("Conversion time: %g", dtime()-t0); - FREE(newima); /* // mirror image around Y int w3 = w*3, h1 = h-1, wsz = w3*sizeof(GLubyte); @@ -672,7 +686,7 @@ static void change_displayed_image(cc_IMG *img){ }*/ DBG("Unlock"); win->image->changed = 1; - //pthread_mutex_unlock(&win->mutex); + pthread_mutex_unlock(&win->mutex); } void closeGL(){ // killed by external signal or ctrl+c @@ -704,7 +718,11 @@ int viewer(imagefunc newimage){ WARNX(_("Can't open OpenGL window, image preview will be inaccessible")); return 1; } - cc_IMG *img = NULL; + static cc_IMG *locimage = NULL; + if(!locimage){ + locimage = cc_newimage(16, 1024, 1024); + if(!locimage) return 1; + } //double t0 = dtime(); while(1){ if(!win || win->killthread){ // got kill from ctrl+q @@ -717,10 +735,10 @@ int viewer(imagefunc newimage){ } if((win->winevt & WINEVT_GETIMAGE) || !(win->winevt & WINEVT_PAUSE)){ //DBG("CHK new image, t=%g", dtime()-t0); - if(newimage(&img)){ + if(newimage(locimage)){ TIMESTAMP("got image -> change"); win->winevt &= ~WINEVT_GETIMAGE; - change_displayed_image(img); // change image if refreshed + change_displayed_image(locimage); // change image if refreshed TIMESTAMP("changed"); } //DBG("Next cycle, t=%g", dtime()-t0); @@ -737,19 +755,19 @@ int viewer(imagefunc newimage){ GP->outfileprefix = strdup("ccd_capture-screenshot"); verbose(VERBOSE_PRIMARY, _("Set output prefix to %s"), GP->outfileprefix); } - saveFITS(img, NULL); + saveFITS(locimage, NULL); win->winevt &= ~WINEVT_SAVEIMAGE; } if(win->winevt & WINEVT_ROLLCOLORFUN){ roll_colorfun(); win->winevt &= ~WINEVT_ROLLCOLORFUN; - change_displayed_image(img); + change_displayed_image(locimage); } if(win->winevt & WINEVT_EQUALIZE){ win->winevt &= ~WINEVT_EQUALIZE; imequalize = !imequalize; verbose(VERBOSE_PRIMARY, _("Equalization of histogram: %s"), imequalize ? N_("on") : N_("off")); - change_displayed_image(img); + change_displayed_image(locimage); } } } diff --git a/imageview.h b/imageview.h index aa162ba..4f7bf02 100644 --- a/imageview.h +++ b/imageview.h @@ -54,7 +54,8 @@ typedef struct{ int ID; // identificator of OpenGL window char *title; // title of window GLuint Tex; // texture for image inside window - rawimage *image; // raw image data + rawimage *image; // colour image data + uint8_t *rawdata; // raw data after processing int w; int h; // window size float x; float y; // image offset coordinates float x0; float y0; // center of window for coords conversion @@ -82,6 +83,6 @@ void conv_mouse_to_image_coords(int x, int y, float *X, float *Y, windowData *wi void conv_image_to_mouse_coords(float X, float Y, int *x, int *y, windowData *window); windowData* getWin(); -typedef int (*imagefunc)(cc_IMG**); +typedef int (*imagefunc)(cc_IMG*); int viewer(imagefunc); diff --git a/locale/ru/messages.po b/locale/ru/messages.po index cadd8bc..75441c9 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: 2026-07-14 14:47+0300\n" +"POT-Creation-Date: 2026-07-21 09:39+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,46 +28,46 @@ msgstr "" msgid "Get signal %d - exit" msgstr "" -#: main.c:91 +#: main.c:88 msgid "Can't use outfile name and prefix together" msgstr "" -#: main.c:94 ccdfunc.c:213 +#: main.c:91 ccdfunc.c:214 #, c-format msgid "File %s exists!" msgstr "" -#: main.c:97 +#: main.c:94 #, c-format msgid "Can't set answer timeout to %g" msgstr "" -#: main.c:101 +#: main.c:98 msgid "" "Options `port` and `path` can't be used together! Point `port` for TCP " "socket or `path` for UNIX." msgstr "" -#: main.c:106 +#: main.c:103 #, c-format msgid "Wrong port value: %d" msgstr "" -#: main.c:119 +#: main.c:116 #, c-format msgid "Set image port to %s\n" msgstr "" -#: main.c:122 +#: main.c:119 msgid "Can't be client and standalone in same time!" msgstr "" -#: main.c:127 +#: main.c:124 #, c-format msgid "Log file %s @ level %d\n" msgstr "" -#: main.c:129 +#: main.c:126 msgid "Can't create log file" msgstr "" @@ -331,546 +331,566 @@ msgstr "" msgid "%d unused parameters:\n" msgstr "" -#: ccdfunc.c:202 +#: ccdfunc.c:203 msgid "Image not saved: neither filename nor filename prefix pointed" msgstr "" -#: ccdfunc.c:220 +#: ccdfunc.c:221 #, c-format msgid "Can't save file with prefix %s" msgstr "" -#: ccdfunc.c:280 +#: ccdfunc.c:283 #, c-format msgid "File saved as '%s'" msgstr "" -#: ccdfunc.c:289 +#: ccdfunc.c:292 msgid "Error saving file" msgstr "" -#: ccdfunc.c:344 +#: ccdfunc.c:347 #, c-format msgid "Image stat:\n" msgstr "" -#: ccdfunc.c:353 +#: ccdfunc.c:356 msgid "Focuser device not pointed" msgstr "" -#: ccdfunc.c:360 +#: ccdfunc.c:363 msgid "No focusers found" msgstr "" -#: ccdfunc.c:384 +#: ccdfunc.c:387 #, c-format msgid "Found focuser #%d: %s\n" msgstr "" -#: ccdfunc.c:390 +#: ccdfunc.c:393 #, c-format msgid "Found %d focusers, you point number %d" msgstr "" -#: ccdfunc.c:394 +#: ccdfunc.c:397 msgid "Can't set active focuser number" msgstr "" -#: ccdfunc.c:408 +#: ccdfunc.c:411 msgid "Can't get focuser limit positions" msgstr "" -#: ccdfunc.c:415 +#: ccdfunc.c:418 msgid "Can't get current focuser position" msgstr "" -#: ccdfunc.c:429 +#: ccdfunc.c:432 #, c-format msgid "Can't set position %g: out of limits [%g, %g]" msgstr "" -#: ccdfunc.c:433 +#: ccdfunc.c:436 msgid "Can't home focuser" msgstr "" -#: ccdfunc.c:435 +#: ccdfunc.c:438 #, c-format msgid "Can't set position %g" msgstr "" -#: ccdfunc.c:443 +#: ccdfunc.c:446 msgid "Wheel device not pointed" msgstr "" -#: ccdfunc.c:450 +#: ccdfunc.c:453 msgid "No wheels found" msgstr "" -#: ccdfunc.c:474 +#: ccdfunc.c:477 #, c-format msgid "Found wheel #%d: %s\n" msgstr "" -#: ccdfunc.c:480 +#: ccdfunc.c:483 #, c-format msgid "Found %d wheels, you point number %d" msgstr "" -#: ccdfunc.c:484 +#: ccdfunc.c:487 msgid "Can't set active wheel number" msgstr "" -#: ccdfunc.c:489 +#: ccdfunc.c:492 #, c-format msgid "Wheel model: %s" msgstr "" -#: ccdfunc.c:498 +#: ccdfunc.c:501 msgid "Can't get current wheel position" msgstr "" -#: ccdfunc.c:500 +#: ccdfunc.c:503 msgid "Can't get max wheel position" msgstr "" -#: ccdfunc.c:507 +#: ccdfunc.c:510 #, c-format msgid "Wheel position should be from 0 to %d" msgstr "" -#: ccdfunc.c:511 +#: ccdfunc.c:514 #, c-format msgid "Can't set wheel position %d" msgstr "" -#: ccdfunc.c:526 +#: ccdfunc.c:529 msgid "Camera plugin have no capture polling funtion." msgstr "" -#: ccdfunc.c:532 +#: ccdfunc.c:535 #, c-format msgid "%.1f seconds till exposition ends" msgstr "" -#: ccdfunc.c:547 +#: ccdfunc.c:550 msgid "Camera device not pointed" msgstr "" -#: ccdfunc.c:554 ccdfunc.c:555 +#: ccdfunc.c:557 ccdfunc.c:558 msgid "No cameras found" msgstr "" -#: ccdfunc.c:575 +#: ccdfunc.c:578 msgid "Camera plugin have no model name getter" msgstr "" -#: ccdfunc.c:580 +#: ccdfunc.c:583 #, c-format msgid "Found camera #%d: %s\n" msgstr "" -#: ccdfunc.c:586 +#: ccdfunc.c:589 #, c-format msgid "Found %d cameras, you point number %d" msgstr "" -#: ccdfunc.c:590 +#: ccdfunc.c:593 msgid "Can't set active camera number" msgstr "" -#: ccdfunc.c:596 +#: ccdfunc.c:599 msgid "Camera plugin have no custom commands" msgstr "" -#: ccdfunc.c:605 ccdfunc.c:608 +#: ccdfunc.c:608 ccdfunc.c:611 #, c-format msgid "Command '%s'" msgstr "" -#: ccdfunc.c:610 +#: ccdfunc.c:613 #, c-format msgid " returns \"%s\"" msgstr "" -#: ccdfunc.c:621 +#: ccdfunc.c:624 msgid "Camera plugin have no fun speed setter" msgstr "" -#: ccdfunc.c:624 +#: ccdfunc.c:627 msgid "Can't set fan speed" msgstr "" -#: ccdfunc.c:625 +#: ccdfunc.c:628 #, c-format msgid "Set fan speed to %d" msgstr "" -#: ccdfunc.c:630 +#: ccdfunc.c:633 #, c-format msgid "Camera model: %s" msgstr "" -#: ccdfunc.c:631 +#: ccdfunc.c:634 #, c-format msgid "Pixel size: %g x %g" msgstr "" -#: ccdfunc.c:637 +#: ccdfunc.c:640 #, c-format msgid "Full array: %s" msgstr "" -#: ccdfunc.c:640 +#: ccdfunc.c:643 #, c-format msgid "Field of view: %s" msgstr "" -#: ccdfunc.c:643 +#: ccdfunc.c:646 #, c-format msgid "Current format: %s" msgstr "" -#: ccdfunc.c:646 +#: ccdfunc.c:649 #, c-format msgid "Maximal geometry (WxH): %dx%d" msgstr "" -#: ccdfunc.c:647 +#: ccdfunc.c:650 #, c-format msgid "Minimal offset: %dx%d" msgstr "" -#: ccdfunc.c:648 +#: ccdfunc.c:651 #, c-format msgid "Geometry steps: offset - %dx%d, size - %dx%d" msgstr "" -#: ccdfunc.c:652 +#: ccdfunc.c:655 #, c-format msgid "Current binning: %d x %d" msgstr "" -#: ccdfunc.c:655 +#: ccdfunc.c:658 #, c-format msgid "Current settings: %d bits per pixel" msgstr "" -#: ccdfunc.c:658 +#: ccdfunc.c:661 #, c-format msgid "Current brightness: %g" msgstr "" -#: ccdfunc.c:660 +#: ccdfunc.c:663 #, c-format msgid "Current gain: %g" msgstr "" -#: ccdfunc.c:662 +#: ccdfunc.c:665 #, c-format msgid "Maximal gain: %g" msgstr "" -#: ccdfunc.c:664 +#: ccdfunc.c:667 msgid "Camera plugin have no temperature setter" msgstr "" -#: ccdfunc.c:665 +#: ccdfunc.c:668 #, c-format msgid "Can't set T to %g degC" msgstr "" -#: ccdfunc.c:673 +#: ccdfunc.c:676 #, c-format msgid "Shutter command: %s\n" msgstr "" -#: ccdfunc.c:675 +#: ccdfunc.c:678 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr "" -#: ccdfunc.c:678 +#: ccdfunc.c:681 #, c-format msgid "Try to configure I/O port as %d" msgstr "" -#: ccdfunc.c:680 +#: ccdfunc.c:683 msgid "Can't configure (unsupported?)" msgstr "" -#: ccdfunc.c:686 +#: ccdfunc.c:689 msgid "Can't get IOport state (unsupported?)" msgstr "" -#: ccdfunc.c:689 +#: ccdfunc.c:692 #, c-format msgid "Try to write %d to I/O port" msgstr "" -#: ccdfunc.c:691 +#: ccdfunc.c:694 msgid "Can't set IOport" msgstr "" -#: ccdfunc.c:698 +#: ccdfunc.c:701 #, c-format msgid "Set gain to %g" msgstr "" -#: ccdfunc.c:699 +#: ccdfunc.c:702 #, c-format msgid "Can't set gain to %g" msgstr "" -#: ccdfunc.c:704 +#: ccdfunc.c:707 #, c-format msgid "Set brightness to %g" msgstr "" -#: ccdfunc.c:705 +#: ccdfunc.c:708 #, c-format msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:711 server.c:330 +#: ccdfunc.c:714 server.c:353 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:723 server.c:331 +#: ccdfunc.c:726 server.c:354 msgid "Can't set given geometry" msgstr "" -#: ccdfunc.c:727 +#: ccdfunc.c:730 #, c-format msgid "Can't set %d flushes" msgstr "" -#: ccdfunc.c:730 +#: ccdfunc.c:733 msgid "Camera plugin have no exposition setter" msgstr "" -#: ccdfunc.c:732 +#: ccdfunc.c:735 #, c-format msgid "Can't set exposure time to %f seconds" msgstr "" -#: ccdfunc.c:735 +#: ccdfunc.c:738 msgid "Can't change frame type" msgstr "" -#: ccdfunc.c:738 +#: ccdfunc.c:741 msgid "Can't set bit depth" msgstr "" -#: ccdfunc.c:740 +#: ccdfunc.c:743 msgid "Can't set readout speed" msgstr "" -#: ccdfunc.c:741 +#: ccdfunc.c:744 #, c-format msgid "Readout mode: %s" msgstr "" -#: ccdfunc.c:742 +#: ccdfunc.c:745 msgid "Only show statistics" msgstr "" -#: ccdfunc.c:745 +#: ccdfunc.c:748 msgid "Can't get current binning" msgstr "" -#: ccdfunc.c:770 +#: ccdfunc.c:773 #, c-format msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:771 ccdfunc.c:848 server.c:195 +#: ccdfunc.c:774 ccdfunc.c:852 server.c:203 msgid "Camera plugin have no function `start exposition`" msgstr "" -#: ccdfunc.c:773 ccdfunc.c:850 server.c:201 +#: ccdfunc.c:776 ccdfunc.c:854 server.c:208 msgid "Can't start exposition" msgstr "" -#: ccdfunc.c:778 +#: ccdfunc.c:781 msgid "Can't capture image" msgstr "" -#: ccdfunc.c:781 +#: ccdfunc.c:784 msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:783 ccdfunc.c:863 server.c:218 +#: ccdfunc.c:786 ccdfunc.c:865 server.c:239 msgid "Camera plugin have no function `capture`" msgstr "" -#: ccdfunc.c:785 ccdfunc.c:864 +#: ccdfunc.c:788 ccdfunc.c:866 msgid "Can't grab image" msgstr "" -#: ccdfunc.c:799 client.c:499 +#: ccdfunc.c:802 client.c:573 #, c-format msgid "%d seconds till pause ends\n" msgstr "" #. for(int i = 0; i < NFRM; ++i) printf("last[%d]=%g\n", i, lastn[i]); -#: ccdfunc.c:834 +#: ccdfunc.c:837 #, c-format msgid "Framerate=%.2f (%g seconds for exp); mean framerate=%.2f" msgstr "" -#: ccdfunc.c:861 +#: ccdfunc.c:863 msgid "Some error when capture" msgstr "" -#: ccdfunc.c:912 +#: ccdfunc.c:904 msgid "Can't create grabbing thread" msgstr "" -#: ccdfunc.c:943 +#: ccdfunc.c:935 msgid "Point network port or UNIX-socket path" msgstr "" -#: ccdfunc.c:947 +#: ccdfunc.c:939 msgid "start_socket(): can't open socket" msgstr "" -#: ccdfunc.c:956 +#: ccdfunc.c:948 msgid "Need exposition time!" msgstr "" -#: server.c:126 +#: server.c:129 msgid "Can't unlock socket mutex" msgstr "" -#: server.c:163 +#: server.c:167 msgid "Can't allocate memory for image" msgstr "" -#: server.c:247 +#: server.c:216 +msgid "Camera disconnected" +msgstr "" + +#: server.c:222 +msgid "Something's wrong with camera" +msgstr "" + +#: server.c:270 msgid "No camera device" msgstr "" -#: server.c:1060 +#: server.c:1092 msgid "server(): need at least command socket fd" msgstr "" -#: server.c:1061 +#: server.c:1093 msgid "Server run without image transport socket" msgstr "" -#: server.c:1082 +#: server.c:1115 msgid "No devices found" msgstr "" -#: server.c:1127 +#: server.c:1160 msgid "Client wants an image, but there's no data" msgstr "" -#: server.c:1156 +#: server.c:1189 msgid "Limit of connections reached" msgstr "" -#: server.c:1225 +#: server.c:1258 #, c-format msgid "Can't create %s" msgstr "" -#: server.c:1261 +#: server.c:1294 msgid "Can't lock mutex" msgstr "" #. send message and wait any answer #. send message and wait answer starting with 'cmd' #. send command and wait for answer on it -#: client.c:42 client.c:44 client.c:46 client.c:276 +#: client.c:42 client.c:44 client.c:46 client.c:288 msgid "Server disconnected" msgstr "" -#: client.c:173 +#: client.c:124 +msgid "Can't allocate buffer" +msgstr "" + +#: client.c:149 +msgid "Server disconnected?" +msgstr "" + +#: client.c:157 +msgid "Got empty string" +msgstr "" + +#: client.c:186 msgid "Send custom plugin commands\n" msgstr "" -#: client.c:307 +#: client.c:340 msgid "Can't lock shared memory" msgstr "" -#: client.c:316 -msgid "getimage(): can't open image transport socket" +#: client.c:359 +msgid "Can't open image transport socket" msgstr "" -#: client.c:319 -msgid "Can't read image header" +#: client.c:365 +msgid "Can't read image header over socket" msgstr "" -#: client.c:324 -msgid "Wrong image: bad magick" -msgstr "" - -#: client.c:328 -msgid "Wrong image size" -msgstr "" - -#: client.c:342 -msgid "Can't reallocate memory for image buffer" -msgstr "" - -#: client.c:361 +#: client.c:398 client.c:428 msgid "Can't read image data" msgstr "" -#: client.c:380 +#: client.c:440 +msgid "Too many FITS headers, truncating" +msgstr "" + +#: client.c:451 #, c-format msgid "Can't read full header, got %zd records from %zd" msgstr "" -#: client.c:414 client.c:517 +#: client.c:466 +msgid "Still got old image" +msgstr "" + +#: client.c:491 client.c:591 msgid "Can't run without command socket" msgstr "" -#: client.c:436 +#: client.c:510 msgid "Exposing frame 1..." msgstr "" -#: client.c:439 +#: client.c:512 msgid "Wait for exposition end" msgstr "" -#: client.c:457 +#: client.c:531 msgid "Can't make exposition" msgstr "" #. start next capture #. last image -> should re-expose -#: client.c:459 client.c:470 client.c:489 +#: client.c:533 client.c:544 client.c:563 #, c-format msgid "Exposing frame %d..." msgstr "" -#: client.c:477 +#: client.c:551 msgid "Frame ready, try to grab" msgstr "" -#: client.c:479 +#: client.c:553 msgid "Can't get next image" msgstr "" -#: client.c:487 +#: client.c:561 msgid "Got already saved image, wait next" msgstr "" -#: client.c:511 +#: client.c:585 msgid "Server timeout" msgstr "" -#: client.c:560 +#: client.c:636 +msgid "Camera in error state" +msgstr "" + +#: client.c:638 #, c-format msgid "" "Image wasn't received, state: %d, waiting: %g, lastNo: %d, curNo: %d " "(timeout: %g)" msgstr "" -#: client.c:620 client.c:627 +#: client.c:698 client.c:705 msgid "Can't create capturing thread" msgstr "" @@ -878,47 +898,47 @@ msgstr "" msgid "Already initialized!" msgstr "" -#: imageview.c:312 +#: imageview.c:314 msgid "Can't init mutex!" msgstr "" -#: imageview.c:425 +#: imageview.c:427 #, c-format msgid "Histogram conversion: %s" msgstr "" -#: imageview.c:615 +#: imageview.c:616 #, c-format msgid "Missed %zd images" msgstr "" -#: imageview.c:697 +#: imageview.c:711 msgid "No image changing function defined" msgstr "" -#: imageview.c:704 +#: imageview.c:718 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "" #. save image -#: imageview.c:734 +#: imageview.c:752 msgid "Make screenshot" msgstr "" -#: imageview.c:738 +#: imageview.c:756 #, c-format msgid "Set output prefix to %s" msgstr "" -#: imageview.c:751 +#: imageview.c:769 #, c-format msgid "Equalization of histogram: %s" msgstr "" -#: imageview.c:751 +#: imageview.c:769 msgid "on" msgstr "" -#: imageview.c:751 +#: imageview.c:769 msgid "off" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 7ff737c..f7f05fe 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: 2026-07-14 14:45+0300\n" + "POT-Creation-Date: 2026-07-21 09:39+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,17 +16,17 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n" "Content-Type: text/plain; charset=koi8-r\n" "Content-Transfer-Encoding: 8bit\n" -#: ccdfunc.c:610 +#: ccdfunc.c:613 #, c-format msgid " returns \"%s\"" msgstr "" -#: ccdfunc.c:532 +#: ccdfunc.c:535 #, c-format msgid "%.1f seconds till exposition ends" msgstr "%.1f секунд до окончания экспозиции" -#: ccdfunc.c:799 client.c:499 +#: ccdfunc.c:802 client.c:573 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d секунд до окончания паузы\n" @@ -48,320 +48,335 @@ msgstr " msgid "CMOS gain level" msgstr "уровень Gain CMOS" -#: ccdfunc.c:547 +#: ccdfunc.c:550 msgid "Camera device not pointed" msgstr "Устройство свеоприемника не подключено" -#: ccdfunc.c:630 +#: server.c:216 +#, fuzzy +msgid "Camera disconnected" +msgstr "Таймаут сервера" + +#: client.c:636 +msgid "Camera in error state" +msgstr "" + +#: ccdfunc.c:633 #, c-format msgid "Camera model: %s" msgstr "Модель светоприемника: %s" -#: ccdfunc.c:526 +#: ccdfunc.c:529 #, fuzzy msgid "Camera plugin have no capture polling funtion." msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:596 +#: ccdfunc.c:599 msgid "Camera plugin have no custom commands" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:730 +#: ccdfunc.c:733 #, fuzzy msgid "Camera plugin have no exposition setter" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:621 +#: ccdfunc.c:624 #, fuzzy msgid "Camera plugin have no fun speed setter" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:783 ccdfunc.c:863 server.c:218 +#: ccdfunc.c:786 ccdfunc.c:865 server.c:239 #, fuzzy msgid "Camera plugin have no function `capture`" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:771 ccdfunc.c:848 server.c:195 +#: ccdfunc.c:774 ccdfunc.c:852 server.c:203 #, fuzzy msgid "Camera plugin have no function `start exposition`" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:575 +#: ccdfunc.c:578 #, fuzzy msgid "Camera plugin have no model name getter" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:664 +#: ccdfunc.c:667 #, fuzzy msgid "Camera plugin have no temperature setter" msgstr "У плагина камеры нет особых команд" -#: server.c:163 +#: client.c:124 +#, fuzzy +msgid "Can't allocate buffer" +msgstr "Не могу захватить изображение" + +#: server.c:167 #, fuzzy msgid "Can't allocate memory for image" msgstr "Не могу захватить изображение" -#: main.c:122 +#: main.c:119 msgid "Can't be client and standalone in same time!" msgstr "" -#: ccdfunc.c:778 +#: ccdfunc.c:781 msgid "Can't capture image" msgstr "Не могу захватить изображение" -#: ccdfunc.c:735 +#: ccdfunc.c:738 msgid "Can't change frame type" msgstr "Не могу изменить тип кадра" -#: ccdfunc.c:680 +#: ccdfunc.c:683 msgid "Can't configure (unsupported?)" msgstr "Не могу сконфигурировать (опция не поддерживается?)" -#: server.c:1225 +#: server.c:1258 #, fuzzy, c-format msgid "Can't create %s" msgstr "Не могу захватить изображение" -#: client.c:620 client.c:627 +#: client.c:698 client.c:705 #, fuzzy msgid "Can't create capturing thread" msgstr "Не могу захватить изображение" -#: ccdfunc.c:912 +#: ccdfunc.c:904 #, fuzzy msgid "Can't create grabbing thread" msgstr "Не могу установить Gain в %g" -#: main.c:129 +#: main.c:126 #, fuzzy msgid "Can't create log file" msgstr "Не могу захватить изображение" -#: ccdfunc.c:686 +#: ccdfunc.c:689 msgid "Can't get IOport state (unsupported?)" msgstr "Не могу получить состояние порта I/O (не поддерживается?)" -#: ccdfunc.c:745 +#: ccdfunc.c:748 msgid "Can't get current binning" msgstr "Не могу получить текущее значение биннинга" -#: ccdfunc.c:415 +#: ccdfunc.c:418 msgid "Can't get current focuser position" msgstr "Не могу определить текущую позицию фокусера" -#: ccdfunc.c:498 +#: ccdfunc.c:501 #, fuzzy msgid "Can't get current wheel position" msgstr "Не могу определить текущую позицию фокусера" -#: ccdfunc.c:408 +#: ccdfunc.c:411 msgid "Can't get focuser limit positions" msgstr "Не могу определить предельную позицию фокусера" -#: ccdfunc.c:500 +#: ccdfunc.c:503 msgid "Can't get max wheel position" msgstr "Не могу определить предельную позицию колеса" -#: client.c:479 +#: client.c:553 #, fuzzy msgid "Can't get next image" msgstr "Не могу захватить изображение" -#: ccdfunc.c:785 ccdfunc.c:864 +#: ccdfunc.c:788 ccdfunc.c:866 msgid "Can't grab image" msgstr "Не могу захватить изображение" -#: ccdfunc.c:433 +#: ccdfunc.c:436 msgid "Can't home focuser" msgstr "Не могу установить фокусер в нуль" -#: imageview.c:312 +#: imageview.c:314 msgid "Can't init mutex!" msgstr "Не могу инициализировать мьютекс!" -#: server.c:1261 +#: server.c:1294 #, fuzzy msgid "Can't lock mutex" msgstr "Не могу инициализировать мьютекс!" -#: client.c:307 +#: client.c:340 #, fuzzy msgid "Can't lock shared memory" msgstr "Не могу захватить изображение" -#: client.c:457 +#: client.c:531 msgid "Can't make exposition" msgstr "Не могу выполнить экспозицию" -#: imageview.c:704 +#: imageview.c:718 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "Не могу открыть окно OpenGL, отображение будет недоступно" -#: client.c:380 +#: client.c:359 +#, fuzzy +msgid "Can't open image transport socket" +msgstr "Не могу сконфигурировать (опция не поддерживается?)" + +#: client.c:451 #, c-format msgid "Can't read full header, got %zd records from %zd" msgstr "" -#: client.c:361 +#: client.c:398 client.c:428 #, fuzzy msgid "Can't read image data" msgstr "Не могу захватить изображение" -#: client.c:319 +#: client.c:365 #, fuzzy -msgid "Can't read image header" +msgid "Can't read image header over socket" msgstr "Не могу захватить изображение" -#: client.c:342 -msgid "Can't reallocate memory for image buffer" -msgstr "" - -#: ccdfunc.c:675 +#: ccdfunc.c:678 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr "Не могу выполнить команду затвора %s (не поддерживается?)" -#: client.c:414 client.c:517 +#: client.c:491 client.c:591 #, fuzzy msgid "Can't run without command socket" msgstr "Не могу выполнить команду затвора %s (не поддерживается?)" -#: ccdfunc.c:220 +#: ccdfunc.c:221 #, c-format msgid "Can't save file with prefix %s" msgstr "Не могу сохранить файл с префиксом %s" -#: ccdfunc.c:727 +#: ccdfunc.c:730 #, c-format msgid "Can't set %d flushes" msgstr "Не могу установить %d сбросов" -#: ccdfunc.c:691 +#: ccdfunc.c:694 msgid "Can't set IOport" msgstr "Не могу поменять значения порта I/O" -#: ccdfunc.c:665 +#: ccdfunc.c:668 #, c-format msgid "Can't set T to %g degC" msgstr "Не могу установить температуру в %g градЦ" -#: ccdfunc.c:590 +#: ccdfunc.c:593 msgid "Can't set active camera number" msgstr "Не могу установить номер активной камеры" -#: ccdfunc.c:394 +#: ccdfunc.c:397 msgid "Can't set active focuser number" msgstr "Не могу установить номер активного фокусера" -#: ccdfunc.c:484 +#: ccdfunc.c:487 msgid "Can't set active wheel number" msgstr "Не могу установить номер активного колеса" -#: main.c:97 +#: main.c:94 #, fuzzy, c-format msgid "Can't set answer timeout to %g" msgstr "Не могу установить Gain в %g" -#: ccdfunc.c:711 server.c:330 +#: ccdfunc.c:714 server.c:353 #, c-format msgid "Can't set binning %dx%d" msgstr "Не могу установить биннинг %dx%d" -#: ccdfunc.c:738 +#: ccdfunc.c:741 msgid "Can't set bit depth" msgstr "Не могу установить разрядность АЦП" -#: ccdfunc.c:705 +#: ccdfunc.c:708 #, c-format msgid "Can't set brightness to %g" msgstr "Не могу установить яркость в %g" -#: ccdfunc.c:732 +#: ccdfunc.c:735 #, c-format msgid "Can't set exposure time to %f seconds" msgstr "Не могу установить экспозицию в %f секунд" -#: ccdfunc.c:624 +#: ccdfunc.c:627 msgid "Can't set fan speed" msgstr "Не могу установить скорость вентиляторов" -#: ccdfunc.c:699 +#: ccdfunc.c:702 #, c-format msgid "Can't set gain to %g" msgstr "Не могу установить Gain в %g" -#: ccdfunc.c:723 server.c:331 +#: ccdfunc.c:726 server.c:354 msgid "Can't set given geometry" msgstr "Не могу установить геометрию" -#: ccdfunc.c:435 +#: ccdfunc.c:438 #, c-format msgid "Can't set position %g" msgstr "Не могу изменить позицию на %g" -#: ccdfunc.c:429 +#: ccdfunc.c:432 #, c-format msgid "Can't set position %g: out of limits [%g, %g]" msgstr "Не могу установить позицию %g: вне пределов [%g, %g]" -#: ccdfunc.c:740 +#: ccdfunc.c:743 msgid "Can't set readout speed" msgstr "Не могу установить скорость считывания" -#: ccdfunc.c:511 +#: ccdfunc.c:514 #, c-format msgid "Can't set wheel position %d" msgstr "Не могу установить положение колеса %d" -#: ccdfunc.c:773 ccdfunc.c:850 server.c:201 +#: ccdfunc.c:776 ccdfunc.c:854 server.c:208 msgid "Can't start exposition" msgstr "Не могу начать экспозицию" -#: server.c:126 +#: server.c:129 #, fuzzy msgid "Can't unlock socket mutex" msgstr "Не могу инициализировать мьютекс!" -#: main.c:91 +#: main.c:88 #, fuzzy msgid "Can't use outfile name and prefix together" msgstr "Не могу сохранить файл с префиксом %s" -#: ccdfunc.c:770 +#: ccdfunc.c:773 #, c-format msgid "Capture frame %d" msgstr "Захват кадра %d" -#: server.c:1127 +#: server.c:1160 msgid "Client wants an image, but there's no data" msgstr "" -#: ccdfunc.c:605 ccdfunc.c:608 +#: ccdfunc.c:608 ccdfunc.c:611 #, c-format msgid "Command '%s'" msgstr "" -#: ccdfunc.c:652 +#: ccdfunc.c:655 #, fuzzy, c-format msgid "Current binning: %d x %d" msgstr "Не могу установить биннинг %dx%d" -#: ccdfunc.c:658 +#: ccdfunc.c:661 #, fuzzy, c-format msgid "Current brightness: %g" msgstr "Установить яркость в %g" -#: ccdfunc.c:643 +#: ccdfunc.c:646 #, c-format msgid "Current format: %s" msgstr "Текущий формат: %s" -#: ccdfunc.c:660 +#: ccdfunc.c:663 #, fuzzy, c-format msgid "Current gain: %g" msgstr "Текущий формат: %s" -#: ccdfunc.c:655 +#: ccdfunc.c:658 #, c-format msgid "Current settings: %d bits per pixel" msgstr "" @@ -370,91 +385,91 @@ msgstr "" msgid "Display image in OpenGL window" msgstr "отображение изображения в окне OpenGL" -#: imageview.c:751 +#: imageview.c:769 #, c-format msgid "Equalization of histogram: %s" msgstr "Эквализация гистограммы: %s" -#: ccdfunc.c:289 +#: ccdfunc.c:292 msgid "Error saving file" msgstr "Ошибка сохранения файла" #. start next capture #. last image -> should re-expose -#: client.c:459 client.c:470 client.c:489 +#: client.c:533 client.c:544 client.c:563 #, c-format msgid "Exposing frame %d..." msgstr "" -#: client.c:436 +#: client.c:510 msgid "Exposing frame 1..." msgstr "" -#: ccdfunc.c:640 +#: ccdfunc.c:643 #, c-format msgid "Field of view: %s" msgstr "Поле зрения: %s" -#: main.c:94 ccdfunc.c:213 +#: main.c:91 ccdfunc.c:214 #, c-format msgid "File %s exists!" msgstr "" -#: ccdfunc.c:280 +#: ccdfunc.c:283 #, c-format msgid "File saved as '%s'" msgstr "Файл сохранен как '%s'" -#: ccdfunc.c:353 +#: ccdfunc.c:356 msgid "Focuser device not pointed" msgstr "Устройство фокусера не указано" -#: ccdfunc.c:586 +#: ccdfunc.c:589 #, c-format msgid "Found %d cameras, you point number %d" msgstr "Обнаружено %d камер, вы указали %d" -#: ccdfunc.c:390 +#: ccdfunc.c:393 #, c-format msgid "Found %d focusers, you point number %d" msgstr "Обнаружено %d фокусеров, вы указали %d" -#: ccdfunc.c:480 +#: ccdfunc.c:483 #, c-format msgid "Found %d wheels, you point number %d" msgstr "Обнаружено %d колес, вы указали %d" -#: ccdfunc.c:580 +#: ccdfunc.c:583 #, c-format msgid "Found camera #%d: %s\n" msgstr "" -#: ccdfunc.c:384 +#: ccdfunc.c:387 #, c-format msgid "Found focuser #%d: %s\n" msgstr "" -#: ccdfunc.c:474 +#: ccdfunc.c:477 #, c-format msgid "Found wheel #%d: %s\n" msgstr "" -#: client.c:477 +#: client.c:551 msgid "Frame ready, try to grab" msgstr "" #. for(int i = 0; i < NFRM; ++i) printf("last[%d]=%g\n", i, lastn[i]); -#: ccdfunc.c:834 +#: ccdfunc.c:837 #, c-format msgid "Framerate=%.2f (%g seconds for exp); mean framerate=%.2f" msgstr "" -#: ccdfunc.c:637 +#: ccdfunc.c:640 #, c-format msgid "Full array: %s" msgstr "Полный формат: %s" -#: ccdfunc.c:648 +#: ccdfunc.c:651 #, c-format msgid "Geometry steps: offset - %dx%d, size - %dx%d" msgstr "" @@ -465,11 +480,15 @@ msgstr "" msgid "Get signal %d - exit" msgstr "" -#: client.c:487 +#: client.c:561 msgid "Got already saved image, wait next" msgstr "" -#: imageview.c:425 +#: client.c:157 +msgid "Got empty string" +msgstr "" + +#: imageview.c:427 #, c-format msgid "Histogram conversion: %s" msgstr "Преобразование гистограммы: %s" @@ -478,32 +497,32 @@ msgstr " msgid "INET image socket port" msgstr "порт локального сетевого сокета передачи изображения" -#: ccdfunc.c:202 +#: ccdfunc.c:203 msgid "Image not saved: neither filename nor filename prefix pointed" msgstr "" -#: ccdfunc.c:344 +#: ccdfunc.c:347 #, c-format msgid "Image stat:\n" msgstr "Статистика по изображению: \n" -#: client.c:560 +#: client.c:638 #, c-format msgid "Image wasn't received, state: %d, waiting: %g, lastNo: %d, curNo: %d " "(timeout: %g)" msgstr "" -#: server.c:1156 +#: server.c:1189 msgid "Limit of connections reached" msgstr "" -#: main.c:127 +#: main.c:124 #, c-format msgid "Log file %s @ level %d\n" msgstr "" #. save image -#: imageview.c:734 +#: imageview.c:752 msgid "Make screenshot" msgstr "" @@ -512,22 +531,22 @@ msgstr "" msgid "Master killed with sig=%d" msgstr "" -#: ccdfunc.c:662 +#: ccdfunc.c:665 #, c-format msgid "Maximal gain: %g" msgstr "" -#: ccdfunc.c:646 +#: ccdfunc.c:649 #, c-format msgid "Maximal geometry (WxH): %dx%d" msgstr "" -#: ccdfunc.c:647 +#: ccdfunc.c:650 #, c-format msgid "Minimal offset: %dx%d" msgstr "" -#: imageview.c:615 +#: imageview.c:616 #, c-format msgid "Missed %zd images" msgstr "" @@ -536,63 +555,63 @@ msgstr "" msgid "N flushes before exposing (default: 1)" msgstr "N засвечиваний перед экспозицией (по умолчанию: 1)" -#: ccdfunc.c:956 +#: ccdfunc.c:948 msgid "Need exposition time!" msgstr "" -#: server.c:247 +#: server.c:270 msgid "No camera device" msgstr "Не указано устройство камеры" -#: ccdfunc.c:554 ccdfunc.c:555 +#: ccdfunc.c:557 ccdfunc.c:558 msgid "No cameras found" msgstr "Камер не обнаружено" -#: server.c:1082 +#: server.c:1115 #, fuzzy msgid "No devices found" msgstr "Турелей не обнаружено" -#: ccdfunc.c:360 +#: ccdfunc.c:363 msgid "No focusers found" msgstr "Фокусеров не обнаружено" -#: imageview.c:697 +#: imageview.c:711 msgid "No image changing function defined" msgstr "" -#: ccdfunc.c:450 +#: ccdfunc.c:453 msgid "No wheels found" msgstr "Турелей не обнаружено" -#: ccdfunc.c:742 +#: ccdfunc.c:745 msgid "Only show statistics" msgstr "Только отобразить статистику" -#: main.c:101 +#: main.c:98 msgid "Options `port` and `path` can't be used together! Point `port` for " "TCP socket or `path` for UNIX." msgstr "" -#: ccdfunc.c:631 +#: ccdfunc.c:634 #, c-format msgid "Pixel size: %g x %g" msgstr "Размер пикселя: %g x %g" -#: ccdfunc.c:943 +#: ccdfunc.c:935 msgid "Point network port or UNIX-socket path" msgstr "" -#: ccdfunc.c:781 +#: ccdfunc.c:784 msgid "Read grabbed image" msgstr "Считывание изображения" -#: ccdfunc.c:741 +#: ccdfunc.c:744 #, c-format msgid "Readout mode: %s" msgstr "Режим считывания: %s" -#: client.c:173 +#: client.c:186 #, fuzzy msgid "Send custom plugin commands\n" msgstr "особые команды плагина камеры" @@ -600,59 +619,76 @@ msgstr " #. send message and wait any answer #. send message and wait answer starting with 'cmd' #. send command and wait for answer on it -#: client.c:42 client.c:44 client.c:46 client.c:276 +#: client.c:42 client.c:44 client.c:46 client.c:288 #, fuzzy msgid "Server disconnected" msgstr "Таймаут сервера" -#: server.c:1061 +#: client.c:149 +#, fuzzy +msgid "Server disconnected?" +msgstr "Таймаут сервера" + +#: server.c:1093 msgid "Server run without image transport socket" msgstr "" -#: client.c:511 +#: client.c:585 msgid "Server timeout" msgstr "Таймаут сервера" -#: ccdfunc.c:704 +#: ccdfunc.c:707 #, c-format msgid "Set brightness to %g" msgstr "Установить яркость в %g" -#: ccdfunc.c:625 +#: ccdfunc.c:628 #, c-format msgid "Set fan speed to %d" msgstr "Не могу установить скорость вентиляторов в %d" -#: ccdfunc.c:698 +#: ccdfunc.c:701 #, c-format msgid "Set gain to %g" msgstr "Установить Gain в %g" -#: main.c:119 +#: main.c:116 #, fuzzy, c-format msgid "Set image port to %s\n" msgstr "Не могу установить скорость вентиляторов в %d" -#: imageview.c:738 +#: imageview.c:756 #, c-format msgid "Set output prefix to %s" msgstr "" -#: ccdfunc.c:673 +#: ccdfunc.c:676 #, c-format msgid "Shutter command: %s\n" msgstr "Команда затвора: %s\n" -#: ccdfunc.c:861 +#: ccdfunc.c:863 msgid "Some error when capture" msgstr "Ошибка при захвате" -#: ccdfunc.c:678 +#: server.c:222 +msgid "Something's wrong with camera" +msgstr "" + +#: client.c:466 +msgid "Still got old image" +msgstr "" + +#: client.c:440 +msgid "Too many FITS headers, truncating" +msgstr "" + +#: ccdfunc.c:681 #, c-format msgid "Try to configure I/O port as %d" msgstr "Попытка сконфигурировать порт I/O как %d" -#: ccdfunc.c:689 +#: ccdfunc.c:692 #, c-format msgid "Try to write %d to I/O port" msgstr "Попытка записи %d в порт I/O" @@ -661,34 +697,26 @@ msgstr " msgid "UNIX socket name (command socket)" msgstr "имя UNIX-сокета" -#: client.c:439 +#: client.c:512 #, fuzzy msgid "Wait for exposition end" msgstr "ждать, пока не кончится экспозиция" -#: ccdfunc.c:443 +#: ccdfunc.c:446 msgid "Wheel device not pointed" msgstr "Устройство турели не указано" -#: ccdfunc.c:489 +#: ccdfunc.c:492 #, fuzzy, c-format msgid "Wheel model: %s" msgstr "Модель светоприемника: %s" -#: ccdfunc.c:507 +#: ccdfunc.c:510 #, c-format msgid "Wheel position should be from 0 to %d" msgstr "Позиция колеса должна быть от 0 до %d" -#: client.c:328 -msgid "Wrong image size" -msgstr "" - -#: client.c:324 -msgid "Wrong image: bad magick" -msgstr "" - -#: main.c:106 +#: main.c:103 #, c-format msgid "Wrong port value: %d" msgstr "" @@ -775,10 +803,6 @@ msgstr "" msgid "get value of I/O port pins" msgstr "получить значение порта I/O" -#: client.c:316 -msgid "getimage(): can't open image transport socket" -msgstr "" - #: cmdlnopts.c:92 msgid "horizontal binning to N pixels" msgstr "горизонтальный биннинг в N пикселей" @@ -844,11 +868,11 @@ msgstr " msgid "observing program name" msgstr "название программы" -#: imageview.c:751 +#: imageview.c:769 msgid "off" msgstr "выкл" -#: imageview.c:751 +#: imageview.c:769 msgid "on" msgstr "вкл" @@ -892,7 +916,7 @@ msgstr " msgid "run in 8-bit mode" msgstr "8-битный режим" -#: server.c:1060 +#: server.c:1092 msgid "server(): need at least command socket fd" msgstr "" @@ -928,7 +952,7 @@ msgstr " msgid "start (!=0) or stop(==0) infinity capturing loop" msgstr "начать (!=0) или закончить (==0) бесконечный цикл захвата изображений" -#: ccdfunc.c:947 +#: ccdfunc.c:939 msgid "start_socket(): can't open socket" msgstr "" diff --git a/main.c b/main.c index c7aceed..fca1ee3 100644 --- a/main.c +++ b/main.c @@ -58,16 +58,13 @@ void signals(int signo){ if(!GP->client){ DBG("Cancel capturing and close all"); stop_server(); - camstop(); - closewheel(); - focclose(); - } + }else exit(signo); #ifdef IMAGEVIEW DBG("KILL GL"); closeGL(); #endif - DBG("exit(%d)", signo); - exit(signo); + //DBG("exit(%d)", signo); + //exit(signo); } int main(int argc, char **argv){ @@ -148,7 +145,7 @@ int main(int argc, char **argv){ return start_socket(isserver); } #ifdef IMAGEVIEW - if(GP->showimage){ // activate image vindow in capture or simple viewer mode + if(GP->showimage){ // activate image window in capture or simple viewer mode imagefunc imfn = NULL; if(GP->cameradev || GP->commondev){if(camerainit) imfn = ccdcaptured;} // capture mode else imfn = NULL; // TODO - simple file viewer diff --git a/server.c b/server.c index ffc2828..c34a12b 100644 --- a/server.c +++ b/server.c @@ -43,6 +43,9 @@ static _Atomic cc_camera_state camstate = CAMERA_IDLE; static atomic_int camflags = 0, camfanspd = 0, confio = 0, nflushes, infty = 0; static cc_frameformat frmformatmax = {0}, curformat = {0}; // maximal format +// image in shared memory +static cc_IMG *ima = NULL; + static float focmaxpos = 0., focminpos = 0.; // focuser extremal positions static int wmaxpos = 0.; // wheel max pos static float tremain = 0.; // time when capture done @@ -114,10 +117,10 @@ static pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/ // return TRUE if `locmutex` can be locked static int lock(){ if(pthread_mutex_trylock(&locmutex)){ - //DBG("\n\nAlready locked"); + DBG("\n\nAlready locked &locmutex"); return FALSE; } - //DBG("LOCK()"); + //DBG("\n\nLOCK(&locmutex)"); return TRUE; } static void unlock(){ @@ -125,11 +128,9 @@ static void unlock(){ LOGERR("Can't unlock socket mutex"); ERR(_("Can't unlock socket mutex")); } - //DBG("UNLOCK()"); + //DBG("\n\nUNLOCK(&locmutex)"); } -static cc_IMG *ima = NULL; - // cleanup semaphore, stop server processes void stop_server(){ isrunning = 0; @@ -139,6 +140,7 @@ void stop_server(){ if(isrunning == -1) break; usleep(1000); } + DBG("OK, remove semaphore..."); // destroy semaphore cc_remove_sem(); } @@ -150,8 +152,9 @@ static void fixima(){ int locked = FALSE; TIMESTAMP("Lock socket"); // lock socket operations - while(!(locked = lock()) && sl_dtime() - t0 < 0.5) usleep(1000); + while(!(locked = lock()) && sl_dtime() - t0 < 0.5) usleep(100000); if(!locked){ + LOGDBG("fixima(): force unlock"); DBG("Still locked from outside -> unlock/lock"); while(!lock()) unlock(); // force unlocking if can't do this gracefully }else DBG("LOCK takes %gs", sl_dtime()-t0); @@ -159,13 +162,16 @@ static void fixima(){ TIMESTAMP("Check SHM image"); // allocate memory for largest possible image if(!ima){ - ima = cc_getshm(GP->shmkey, camera->array.h * camera->array.w * 2); + size_t len = camera->array.h * camera->array.w * 2; + ima = cc_getshm(GP->shmkey, len); if(!ima) ERR(_("Can't allocate memory for image")); + ima->datasize = ima->bytelen; // init shared semaphore cc_init_sem(TRUE); } TIMESTAMP("Lock SHM image"); cc_lock_shm(TRUE); + LOGDBG("fixima(): SHM locked"); shmkey = GP->shmkey; //if(raw_width == ima->w && raw_height == ima->h) return; // all OK DBG("curformat: %dx%d", curformat.w, curformat.h); @@ -179,12 +185,14 @@ static void fixima(){ ima->bytelen = raw_height * raw_width * cc_getNbytes(ima); DBG("new image: %dx%d", raw_width, raw_height); cc_unlock_shm(); + LOGDBG("fixima(): SHM UNlocked"); unlock(); TIMESTAMP("All OK"); } // functions for processCAM finite state machine static inline void cameraidlestate(){ // idle - wait for capture commands + static double Tcheck = 0.; if(camflags & FLAG_STARTCAPTURE){ // start capturing TIMESTAMP("Start exposition"); camflags &= ~(FLAG_STARTCAPTURE | FLAG_CANCEL); @@ -194,15 +202,28 @@ static inline void cameraidlestate(){ // idle - wait for capture commands LOGERR("Camera plugin have no function `start exposition`"); WARNX(_("Camera plugin have no function `start exposition`")); camstate = CAMERA_ERROR; - return; } if(!camera->startexposition()){ LOGERR("Can't start exposition"); WARNX(_("Can't start exposition")); camstate = CAMERA_ERROR; - return; } } + if(camstate == CAMERA_ERROR || (camstate == CAMERA_IDLE && sl_dtime() - Tcheck > 5.)){ + Tcheck = sl_dtime(); + if(!camera->check()){ + LOGERR("Camera disconnected"); + ERRX(_("Camera disconnected")); + } + if(camera->setDevNo && !camera->setDevNo(GP->camdevno)){ + LOGERR("Can't set active camera # %d, try 0", GP->camdevno); + if(!camera->setDevNo(0)){ + LOGERR("Can't set active camera # 0, restart"); + ERRX(_("Something's wrong with camera")); + } + } + camstate = CAMERA_IDLE; + } } static inline void cameracapturestate(){ // capturing - wait for exposition ends cc_capture_status cs; @@ -221,6 +242,7 @@ static inline void cameracapturestate(){ // capturing - wait for exposition ends return; } cc_lock_shm(TRUE); + LOGDBG("cameracapturestate(): SHM locked"); if(!camera->capture(ima)){ LOGERR("Can't capture image"); camstate = CAMERA_ERROR; @@ -233,6 +255,7 @@ static inline void cameracapturestate(){ // capturing - wait for exposition ends ++ima->imnumber; // increment counter } cc_unlock_shm(); + LOGDBG("cameracapturestate(): SHM UNlocked"); TIMESTAMP("Captured and unlocked"); } camstate = CAMERA_FRAMERDY; @@ -434,7 +457,7 @@ static cc_hresult binhandler(_U_ int fd, const char *key, const char *val){ if(r){ if(0 == strcmp(key, CC_CMD_HBIN)) snprintf(buf, 63, "%s=%d", key, GP->hbin); else snprintf(buf, 63, "%s=%d", key, GP->vbin); - if(val) fixima(); + //if(val) fixima(); if(!cc_sendstrmessage(fd, buf)) return CC_RESULT_DISCONNECTED; return CC_RESULT_SILENCE; } @@ -590,7 +613,7 @@ static cc_hresult formathandler(int fd, const char *key, const char *val){ if(!r) return CC_RESULT_FAIL; curformat = fmt; DBG("curformat: w=%d, h=%d", curformat.w, curformat.h); - fixima(); + //fixima(); } if(0 == strcmp(key, CC_CMD_FRAMEMAX)) snprintf(buf, 63, CC_CMD_FRAMEMAX "=%d,%d,%d,%d", frmformatmax.xoff, frmformatmax.yoff, frmformatmax.xoff+frmformatmax.w, frmformatmax.yoff+frmformatmax.h); @@ -624,11 +647,11 @@ static cc_hresult expstatehandler(int fd, _U_ const char *key, const char *val){ else if(n == CAMERA_CAPTURE){ // start exposition if(GP->exptime < 1e-9){ // need exposition time to be set return CC_RESULT_FAIL; - } + }/* if(camstate == CAMERA_CAPTURE){ DBG("Capture in process when user ask '%s=%s'", key, val); return CC_RESULT_BUSY; // in progress - } + }*/ TIMESTAMP("Get FLAG_STARTCAPTURE"); TIMEINIT(); camflags |= FLAG_STARTCAPTURE; @@ -658,7 +681,7 @@ static cc_hresult _8bithandler(int fd, _U_ const char *key, const char *val){ int s = atoi(val); if(s != 0 && s != 1) return CC_RESULT_BADVAL; if(!camera->setbitdepth(!s)) return CC_RESULT_FAIL; - fixima(); + //fixima(); GP->_8bit = s; } snprintf(buf, 63, CC_CMD_8BIT "=%d", GP->_8bit); @@ -669,8 +692,10 @@ static cc_hresult imnohandler(int fd, const char *key, const char _U_ *val){ if(!ima) return CC_RESULT_FAIL; char buf[64]; cc_lock_shm(TRUE); + LOGDBG("imnohandler(): SHM locked"); int No = ima->imnumber; cc_unlock_shm(); + LOGDBG("imnohandler(): SHM UNlocked"); snprintf(buf, 63, "%s=%d", key, No); if(!cc_sendstrmessage(fd, buf)) return CC_RESULT_DISCONNECTED; return CC_RESULT_SILENCE; @@ -1025,31 +1050,38 @@ static void *sendimage(void *C){ int client = *(int*)C; if(ima->h < 1 || ima->w < 1) return NULL; DBG("client fd: %d", client); - cc_lock_shm(TRUE); - cc_IMG *locimage = calloc(1, sizeof(cc_IMG)); - void *data = calloc(1, ima->bytelen); - if(!locimage || !data){ - cc_unlock_shm(); - if(data) free(data); - if(locimage) free(locimage); + double t0 = sl_dtime(); + int locked = FALSE; + while(!(locked = cc_lock_shm(FALSE)) && sl_dtime() - t0 < MUTEX_LOCK_TMOUT); + if(!locked){ + LOGERR("sendimage(): can't lock SHM"); + close(client); + return NULL; + } + LOGDBG("sendimage(): SHM locked"); + cc_IMG *locimage = cc_newimage(ima->bitpix, ima->w, ima->h); + if(!locimage || !cc_copyimage(locimage, ima, FALSE)){ + cc_unlock_shm(); + LOGDBG("sendimage(): SHM UNlocked"); + LOGERR("Can't copy new frame to local image"); return NULL; } - memcpy(locimage, ima, sizeof(cc_IMG)); - memcpy(data, ima->data, ima->bytelen); cc_unlock_shm(); + LOGDBG("sendimage(): SHM UNlocked"); do{ // send image body if(!cc_senddata(client, locimage, sizeof(cc_IMG))) break; // send image itself (client can close socket if don't need image data) - if(!cc_senddata(client, data, locimage->bytelen)) break; + if(!cc_senddata(client, locimage->data, locimage->bytelen)) break; // send FITS header (client can close socket if don't need it) for(size_t i = 0; i < locimage->headerstrings; ++i){ // send header if(!cc_senddata(client, &locimage->fitsheader[i], FLEN_CARD)) break; } }while(0); - free(locimage); - free(data); - close(client); + shutdown(client, SHUT_WR); // tell client we are closing socket + recv(client, locimage->data, locimage->bytelen, MSG_NOSIGNAL); // block until client close his side + cc_freeimage(&locimage); + close(client); // OK, we can close socket TIMESTAMP("Image sent"); DBG("%d closed", client); return NULL; @@ -1069,6 +1101,7 @@ void server(int sock, int imsock){ LOGERR("server(): error in listen() for command socket"); return; } + TIMEINIT(); // init everything int ctr = 3; if(startFocuser()) --ctr; @@ -1079,7 +1112,7 @@ void server(int sock, int imsock){ camdevini(0); if(ctr == 3){ LOGERR("server(): no devices found"); - WARNX(_("No devices found")); + ERRX(_("No devices found")); } // start camera thread pthread_t camthread; @@ -1123,7 +1156,7 @@ void server(int sock, int imsock){ DBG("client=%d", client); // sending image could be a very long operation -> run it in separate thread if(client > -1){ - if(ima->imnumber == 0){ + if(!ima || ima->imnumber == 0){ WARNX(_("Client wants an image, but there's no data")); close(client); }else{ @@ -1267,7 +1300,9 @@ static int parsestring(int fd, cc_handleritem *handlers, char *str){ if(h->handler) r = h->handler(fd, str, val); else r = CC_RESULT_FAIL; } - if(l) unlock(); + if(l){ + unlock(); + } if(r == CC_RESULT_DISCONNECTED){ DBG("handler return CC_RESULT_DISCONNECTED"); return FALSE;