Instrument Neutral Distributed Interface INDI  1.9.5
dspinterface.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2017 Jasem Mutlaq. All rights reserved.
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 *******************************************************************************/
18 
19 #include "dspinterface.h"
20 
21 #include "defaultdevice.h"
22 #include "indiccd.h"
23 #include "indisensorinterface.h"
24 #include "indilogger.h"
25 #include "locale_compat.h"
26 #include "indicom.h"
27 #include "libastro.h"
28 #include "indiutility.h"
29 
30 #include <fitsio.h>
31 
32 #include <libnova/julian_day.h>
33 #include <libnova/ln_types.h>
34 #include <libnova/precession.h>
35 
36 #include <regex>
37 
38 #include <dirent.h>
39 #include <cerrno>
40 #include <locale.h>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44 #include <zlib.h>
45 #include <sys/stat.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 
49 static std::string regex_replace_compat(const std::string &input, const std::string &pattern, const std::string &replace)
50 {
51  std::stringstream s;
52  std::regex_replace(std::ostreambuf_iterator<char>(s), input.begin(), input.end(), std::regex(pattern), replace);
53  return s.str();
54 }
55 
56 namespace DSP
57 {
58 const char *DSP_TAB = "Signal Processing";
59 
60 Interface::Interface(INDI::DefaultDevice *dev, Type type, const char *name, const char *label) : m_Device(dev),
61  m_Name(name), m_Label(label), m_Type(type)
62 {
63  char activatestrname[MAXINDINAME];
64  char activatestrlabel[MAXINDILABEL];
65  sprintf(activatestrname, "DSP_ACTIVATE_%s", m_Name);
66  sprintf(activatestrlabel, "Activate %s", m_Label);
67  IUFillSwitch(&ActivateS[0], "DSP_ACTIVATE_ON", "Activate", ISState::ISS_OFF);
68  IUFillSwitch(&ActivateS[1], "DSP_ACTIVATE_OFF", "Deactivate", ISState::ISS_ON);
69  IUFillSwitchVector(&ActivateSP, ActivateS, 2, getDeviceName(), activatestrname, activatestrlabel, DSP_TAB, IP_RW,
70  ISR_1OFMANY, 60, IPS_IDLE);
71 
74  BufferSizes = nullptr;
75  BufferSizesQty = 0;
76  strncpy (FitsB.format, ".fits", MAXINDIFORMAT);
77 }
78 
80 {
81 }
82 
84 {
85  return m_Device->getDeviceName();
86 }
87 
88 void Interface::ISGetProperties(const char *dev)
89 {
90  INDI_UNUSED(dev);
91  if (m_Device->isConnected())
92  {
94  }
95  else
96  {
98  PluginActive = false;
99  Deactivated();
100  }
101 }
102 
104 {
105  if (m_Device->isConnected())
106  {
108  }
109  else
110  {
112  PluginActive = false;
113  Deactivated();
114  }
115  return true;
116 }
117 
118 bool Interface::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
119 {
120  if(!strcmp(dev, getDeviceName()) && !strcmp(name, ActivateSP.name))
121  {
122  IUUpdateSwitch(&ActivateSP, states, names, n);
123  if(ActivateSP.sp[0].s == ISS_ON)
124  {
125  PluginActive = true;
126  Activated();
127  }
128  else
129  {
130  PluginActive = false;
131  Deactivated();
132  }
133  IDSetSwitch(&ActivateSP, nullptr);
134  }
135  return false;
136 }
137 
138 bool Interface::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
139 {
140  INDI_UNUSED(dev);
141  INDI_UNUSED(name);
142  INDI_UNUSED(values);
143  INDI_UNUSED(names);
144  INDI_UNUSED(n);
145  return false;
146 }
147 
148 bool Interface::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
149 {
150  INDI_UNUSED(dev);
151  INDI_UNUSED(name);
152  INDI_UNUSED(texts);
153  INDI_UNUSED(names);
154  INDI_UNUSED(n);
155  return false;
156 }
157 
158 bool Interface::ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[],
159  char *names[], int n)
160 {
161  INDI_UNUSED(dev);
162  INDI_UNUSED(name);
163  INDI_UNUSED(sizes);
164  INDI_UNUSED(blobsizes);
165  INDI_UNUSED(blobs);
166  INDI_UNUSED(formats);
167  INDI_UNUSED(names);
168  INDI_UNUSED(n);
169  return false;
170 }
171 
172 uint8_t* Interface::Callback(uint8_t* buf, uint32_t ndims, int* dims, int bits_per_sample)
173 {
174  INDI_UNUSED(buf);
175  INDI_UNUSED(ndims);
176  INDI_UNUSED(dims);
177  INDI_UNUSED(bits_per_sample);
178  DEBUG(INDI::Logger::DBG_WARNING, "Interface::Callback - Should never get here");
179  return nullptr;
180 }
181 
182 bool Interface::processBLOB(uint8_t* buf, uint32_t ndims, int* dims, int bits_per_sample)
183 {
184  if(PluginActive)
185  {
186  bool sendCapture = (m_Device->getSwitch("UPLOAD_MODE")->sp[0].s == ISS_ON
187  || m_Device->getSwitch("UPLOAD_MODE")->sp[2].s == ISS_ON);
188  bool saveCapture = (m_Device->getSwitch("UPLOAD_MODE")->sp[1].s == ISS_ON
189  || m_Device->getSwitch("UPLOAD_MODE")->sp[2].s == ISS_ON);
190 
191  if (sendCapture || saveCapture)
192  {
193  setSizes(ndims, dims);
194  setBPS(bits_per_sample);
195  uint8_t* buffer = Callback(buf, ndims, dims, bits_per_sample);
196  if (buffer)
197  {
198  LOGF_INFO("%s processing done. Creating file..", m_Label);
199  if (!strcmp(FitsB.format, ".fits"))
200  {
201  sendFITS(buffer, sendCapture, saveCapture);
202  }
203  else
204  {
205  long len = 1;
206  uint32_t i;
207  for (len = 1, i = 0; i < BufferSizesQty; len *= BufferSizes[i++]);
208  len *= getBPS() / 8;
209  uploadFile(buffer, len, sendCapture, saveCapture, FitsB.format);
210  }
211 
212  if (sendCapture)
213  IDSetBLOB(&FitsBP, nullptr);
214  }
215  free(buffer);
216  }
217  }
218  return true;
219 }
220 
222 {
224 }
225 
227 {
229 }
230 
232 {
233  INDI_UNUSED(fp);
234  return true;
235 }
236 
237 void Interface::addFITSKeywords(fitsfile *fptr)
238 {
239  int status = 0;
240  char exp_start[32];
241 
242  char *orig = setlocale(LC_NUMERIC, "C");
243 
244  char fitsString[MAXINDIDEVICE];
245 
246  // Telescope
247  strncpy(fitsString, m_Device->getText("ACTIVE_DEVICES")->tp[0].text, MAXINDIDEVICE);
248  fits_update_key_s(fptr, TSTRING, "TELESCOP", fitsString, "Telescope name", &status);
249 
250  // Observer
251  strncpy(fitsString, m_Device->getText("FITS_HEADER")->tp[0].text, MAXINDIDEVICE);
252  fits_update_key_s(fptr, TSTRING, "OBSERVER", fitsString, "Observer name", &status);
253 
254  // Object
255  strncpy(fitsString, m_Device->getText("FITS_HEADER")->tp[1].text, MAXINDIDEVICE);
256  fits_update_key_s(fptr, TSTRING, "OBJECT", fitsString, "Object name", &status);
257 
258  INumberVectorProperty *nv = m_Device->getNumber("GEOGRAPHIC_COORDS");
259  if(nv != nullptr)
260  {
261  double Lat = nv->np[0].value;
262  double Lon = nv->np[1].value;
263  double El = nv->np[2].value;
264 
265  char lat_str[MAXINDIFORMAT];
266  char lon_str[MAXINDIFORMAT];
267  char el_str[MAXINDIFORMAT];
268  fs_sexa(lat_str, Lat, 2, 360000);
269  fs_sexa(lat_str, Lon, 2, 360000);
270  snprintf(el_str, MAXINDIFORMAT, "%lf", El);
271  fits_update_key_s(fptr, TSTRING, "LATITUDE", lat_str, "Location Latitude", &status);
272  fits_update_key_s(fptr, TSTRING, "LONGITUDE", lon_str, "Location Longitude", &status);
273  fits_update_key_s(fptr, TSTRING, "ELEVATION", el_str, "Location Elevation", &status);
274  }
275 
276  nv = m_Device->getNumber("EQUATORIAL_EOD_COORDS");
277  if(nv != nullptr)
278  {
279  double RA = nv->np[0].value;
280  double Dec = nv->np[1].value;
281 
282  INDI::IEquatorialCoordinates epochPos { 0, 0 }, J2000Pos { 0, 0 };
283  epochPos.rightascension = RA;
284  epochPos.declination = Dec;
285 
286  // Convert from JNow to J2000
287  //TODO use exp_start instead of julian from system
288  INDI::ObservedToJ2000(&epochPos, ln_get_julian_from_sys(), &J2000Pos);
289 
290  double raJ2000 = J2000Pos.rightascension;
291  double decJ2000 = J2000Pos.declination;
292  char ra_str[32], de_str[32];
293 
294  fs_sexa(ra_str, raJ2000, 2, 360000);
295  fs_sexa(de_str, decJ2000, 2, 360000);
296 
297  char *raPtr = ra_str, *dePtr = de_str;
298  while (*raPtr != '\0')
299  {
300  if (*raPtr == ':')
301  *raPtr = ' ';
302  raPtr++;
303  }
304  while (*dePtr != '\0')
305  {
306  if (*dePtr == ':')
307  *dePtr = ' ';
308  dePtr++;
309  }
310 
311  fits_update_key_s(fptr, TSTRING, "OBJCTRA", ra_str, "Object RA", &status);
312  fits_update_key_s(fptr, TSTRING, "OBJCTDEC", de_str, "Object DEC", &status);
313 
314  int epoch = 2000;
315 
316  //fits_update_key_s(fptr, TINT, "EPOCH", &epoch, "Epoch", &status);
317  fits_update_key_s(fptr, TINT, "EQUINOX", &epoch, "Equinox", &status);
318  }
319 
320  fits_update_key_s(fptr, TSTRING, "DATE-OBS", exp_start, "UTC start date of observation", &status);
321  fits_write_comment(fptr, "Generated by INDI", &status);
322 
323  setlocale(LC_NUMERIC, orig);
324 }
325 
326 void Interface::fits_update_key_s(fitsfile *fptr, int type, std::string name, void *p, std::string explanation,
327  int *status)
328 {
329  // this function is for removing warnings about deprecated string conversion to char* (from arg 5)
330  fits_update_key(fptr, type, name.c_str(), p, const_cast<char *>(explanation.c_str()), status);
331 }
332 
334 {
335  dsp_stream_p loaded_stream = dsp_stream_new();
336  long ndims;
337  long bits_per_sample;
338  int status;
339  off_t offset;
340  off_t head;
341  off_t end;
342  fitsfile *fptr;
343  void* buf;
344  char error_status[MAXINDINAME];
345  char comment[MAXINDINAME];
346  char filename[MAXINDIMESSAGE];
347  sprintf(filename, "/tmp/%s_%s_%08X.fits", m_Label, getDeviceName(), rand());
348  int fd = creat(filename, 0600);
349  if(fd >= 0)
350  {
351  int written = write(fd, buffer, len);
352  if(written != len)
353  return nullptr;
354  close(fd);
355  }
356  fits_open_file(&fptr, filename, 0, &status);
357  if(status != 0)
358  goto load_err;
359  fits_read_key_lng(fptr, "BITPIX", &bits_per_sample, comment, &status);
360  if(status != 0)
361  goto load_err;
362  fits_read_key_lng(fptr, "NAXIS", &ndims, comment, &status);
363  if(status != 0)
364  goto load_err;
365  for (int d = 1; d <= ndims; d++)
366  {
367  char query[MAXINDINAME];
368  long value;
369  sprintf(query, "NAXIS%d", d);
370  fits_read_key_lng(fptr, query, &value, comment, &status);
371  if(status != 0)
372  goto load_err;
373  dsp_stream_add_dim(loaded_stream, value);
374  }
375  dsp_stream_alloc_buffer(loaded_stream, loaded_stream->len);
376  fits_get_hduoff(fptr, &head, &offset, &end, &status);
377  buf = static_cast<void*>(&buffer[offset]);
378  switch (bits_per_sample)
379  {
380  case 8:
381  dsp_buffer_copy((static_cast<uint8_t *>(buf)), loaded_stream->buf, loaded_stream->len);
382  goto err_free;
383  case 16:
384  dsp_buffer_copy((static_cast<uint16_t *>(buf)), loaded_stream->buf, loaded_stream->len);
385  goto err_free;
386  case 32:
387  dsp_buffer_copy((static_cast<uint32_t *>(buf)), loaded_stream->buf, loaded_stream->len);
388  goto err_free;
389  case 64:
390  dsp_buffer_copy((static_cast<unsigned long *>(buf)), loaded_stream->buf, loaded_stream->len);
391  goto err_free;
392  case -32:
393  dsp_buffer_copy((static_cast<float *>(buf)), loaded_stream->buf, loaded_stream->len);
394  goto err_free;
395  case -64:
396  dsp_buffer_copy((static_cast<double *>(buf)), loaded_stream->buf, loaded_stream->len);
397  goto dsp_err;
398  default:
399  break;
400  }
401 load_err:
402  fits_report_error(stderr, status); /* print out any error messages */
403  fits_get_errstatus(status, error_status);
404  LOGF_ERROR("FITS Error: %s", error_status);
405 dsp_err:
406  //Destroy the dsp stream
407  dsp_stream_free_buffer(loaded_stream);
408  dsp_stream_free(loaded_stream);
409  return nullptr;
410 err_free:
411  fits_close_file(fptr, &status);
412  unlink(filename);
413  return loaded_stream;
414 }
415 
416 bool Interface::sendFITS(uint8_t *buf, bool sendCapture, bool saveCapture)
417 {
418  int img_type = USHORT_IMG;
419  int byte_type = TUSHORT;
420  std::string bit_depth = "16 bits per sample";
421  switch (getBPS())
422  {
423  case 8:
424  byte_type = TBYTE;
425  img_type = BYTE_IMG;
426  bit_depth = "8 bits per sample";
427  break;
428 
429  case 16:
430  byte_type = TUSHORT;
431  img_type = USHORT_IMG;
432  bit_depth = "16 bits per sample";
433  break;
434 
435  case 32:
436  byte_type = TULONG;
437  img_type = ULONG_IMG;
438  bit_depth = "32 bits per sample";
439  break;
440 
441  case 64:
442  byte_type = TLONGLONG;
443  img_type = LONGLONG_IMG;
444  bit_depth = "64 bits double per sample";
445  break;
446 
447  case -32:
448  byte_type = TFLOAT;
449  img_type = FLOAT_IMG;
450  bit_depth = "32 bits double per sample";
451  break;
452 
453  case -64:
454  byte_type = TDOUBLE;
455  img_type = DOUBLE_IMG;
456  bit_depth = "64 bits double per sample";
457  break;
458 
459  default:
460  DEBUGF(INDI::Logger::DBG_ERROR, "Unsupported bits per sample value %d", getBPS());
461  return false;
462  }
463 
464  fitsfile *fptr = nullptr;
465  void *memptr;
466  size_t memsize;
467  int status = 0;
468  int naxis = static_cast<int>(BufferSizesQty);
469  long *naxes = static_cast<long*>(malloc(sizeof(long) * BufferSizesQty));
470  long nelements = 0;
471 
472  for (uint32_t i = 0, nelements = 1; i < BufferSizesQty; nelements *= static_cast<long>(BufferSizes[i++]))
473  naxes[i] = BufferSizes[i];
474  char error_status[MAXINDINAME];
475 
476  // Now we have to send fits format data to the client
477  memsize = 5760;
478  memptr = malloc(memsize);
479  if (!memptr)
480  {
481  LOGF_ERROR("Error: failed to allocate memory: %lu", memsize);
482  return false;
483  }
484 
485  fits_create_memfile(&fptr, &memptr, &memsize, 2880, realloc, &status);
486 
487  if (status)
488  {
489  fits_report_error(stderr, status); /* print out any error messages */
490  fits_get_errstatus(status, error_status);
491  fits_close_file(fptr, &status);
492  free(memptr);
493  LOGF_ERROR("FITS Error: %s", error_status);
494  return false;
495  }
496 
497  fits_create_img(fptr, img_type, naxis, naxes, &status);
498 
499  if (status)
500  {
501  fits_report_error(stderr, status); /* print out any error messages */
502  fits_get_errstatus(status, error_status);
503  fits_close_file(fptr, &status);
504  free(memptr);
505  LOGF_ERROR("FITS Error: %s", error_status);
506  return false;
507  }
508 
509  addFITSKeywords(fptr);
510 
511  fits_write_img(fptr, byte_type, 1, nelements, buf, &status);
512 
513  if (status)
514  {
515  fits_report_error(stderr, status); /* print out any error messages */
516  fits_get_errstatus(status, error_status);
517  fits_close_file(fptr, &status);
518  free(memptr);
519  LOGF_ERROR("FITS Error: %s", error_status);
520  return false;
521  }
522 
523  fits_close_file(fptr, &status);
524 
525  uploadFile(memptr, memsize, sendCapture, saveCapture, "fits");
526  free(memptr);
527  return true;
528 }
529 
530 bool Interface::uploadFile(const void *fitsData, size_t totalBytes, bool sendCapture, bool saveCapture, const char* format)
531 {
532 
533  DEBUGF(INDI::Logger::DBG_DEBUG, "Uploading file. Ext: %s, Size: %d, sendCapture? %s, saveCapture? %s",
534  format, totalBytes, sendCapture ? "Yes" : "No", saveCapture ? "Yes" : "No");
535 
536  FitsB.blob = const_cast<void *>(fitsData);
537  FitsB.bloblen = static_cast<int>(totalBytes);
538  if (saveCapture)
539  {
540 
541  FILE *fp = nullptr;
542 
543  std::string prefix = m_Device->getText("UPLOAD_SETTINGS")->tp[1].text;
544 
545  int maxIndex = getFileIndex(m_Device->getText("UPLOAD_SETTINGS")->tp[0].text, prefix.c_str(),
546  format);
547 
548  if (maxIndex < 0)
549  {
550  DEBUGF(INDI::Logger::DBG_ERROR, "Error iterating directory %s. %s", m_Device->getText("UPLOAD_SETTINGS")->tp[0].text,
551  strerror(errno));
552  return false;
553  }
554 
555  if (maxIndex > 0)
556  {
557  char ts[32];
558  struct tm *tp;
559  time_t t;
560  time(&t);
561  tp = localtime(&t);
562  strftime(ts, sizeof(ts), "%Y-%m-%dT%H-%M-%S", tp);
563  std::string filets(ts);
564  prefix = std::regex_replace(prefix, std::regex("ISO8601"), filets);
565 
566  char indexString[8];
567  snprintf(indexString, 8, "%03d", maxIndex);
568  std::string prefixIndex = indexString;
569  //prefix.replace(prefix.find("XXX"), std::string::npos, prefixIndex);
570  prefix = std::regex_replace(prefix, std::regex("XXX"), prefixIndex);
571  }
572 
573  snprintf(processedFileName, MAXINDINAME, "%s/%s_%s.%s", m_Device->getText("UPLOAD_SETTINGS")->tp[0].text, prefix.c_str(),
574  m_Name, format);
575 
576  fp = fopen(processedFileName, "w");
577  if (fp == nullptr)
578  {
579  DEBUGF(INDI::Logger::DBG_ERROR, "Unable to save image file (%s). %s", processedFileName, strerror(errno));
580  return false;
581  }
582 
583  size_t n = 0;
584  for (size_t nr = 0; nr < static_cast<size_t>(FitsB.bloblen); nr += n)
585  n = fwrite((static_cast<char *>(FitsB.blob) + nr), 1, static_cast<size_t>(FitsB.bloblen - nr), fp);
586 
587  fclose(fp);
588  LOGF_INFO("File saved in %s.", processedFileName);
589  }
590 
591  FitsB.size = totalBytes;
592  FitsBP.s = IPS_OK;
593 
594  if (sendCapture)
595  {
596 
597  auto start = std::chrono::high_resolution_clock::now();
598  IDSetBLOB(&FitsBP, nullptr);
599  auto end = std::chrono::high_resolution_clock::now();
600  std::chrono::duration<double> diff = end - start;
601  LOGF_DEBUG("BLOB transfer took %g seconds", diff.count());
602  }
603 
604 
605  DEBUG(INDI::Logger::DBG_DEBUG, "Upload complete");
606 
607  return true;
608 }
609 
610 int Interface::getFileIndex(const char *dir, const char *prefix, const char *ext)
611 {
612  INDI_UNUSED(ext);
613 
614  DIR *dpdf = nullptr;
615  struct dirent *epdf = nullptr;
616  std::vector<std::string> files = std::vector<std::string>();
617 
618  std::string prefixIndex = prefix;
619  prefixIndex = regex_replace_compat(prefixIndex, "_ISO8601", "");
620  prefixIndex = regex_replace_compat(prefixIndex, "_XXX", "");
621 
622  // Create directory if does not exist
623  struct stat st;
624 
625  if (stat(dir, &st) == -1)
626  {
627  LOGF_DEBUG("Creating directory %s...", dir);
628  if (INDI::mkpath(dir, 0755) == -1)
629  LOGF_ERROR("Error creating directory %s (%s)", dir, strerror(errno));
630  }
631 
632  dpdf = opendir(dir);
633  if (dpdf != nullptr)
634  {
635  while ((epdf = readdir(dpdf)))
636  {
637  if (strstr(epdf->d_name, prefixIndex.c_str()))
638  files.push_back(epdf->d_name);
639  }
640  closedir(dpdf);
641  }
642  else
643  return -1;
644 
645  int maxIndex = 0;
646 
647  for (unsigned long i = 0; i < static_cast<unsigned long>(files.size()); i++)
648  {
649  int index = -1;
650 
651  std::string file = files.at(i);
652  std::size_t start = file.find_last_of("_");
653  std::size_t end = file.find_last_of(".");
654  if (start != std::string::npos)
655  {
656  index = atoi(file.substr(start + 1, end).c_str());
657  if (index > maxIndex)
658  maxIndex = index;
659  }
660  }
661 
662  return (maxIndex + 1);
663 }
664 
665 void Interface::setStream(void *buf, uint32_t dims, int *sizes, int bits_per_sample)
666 {
667  //Create the dsp stream
669  for(uint32_t dim = 0; dim < dims; dim++)
670  dsp_stream_add_dim(stream, sizes[dim]);
672  switch (bits_per_sample)
673  {
674  case 8:
675  dsp_buffer_copy((static_cast<uint8_t *>(buf)), stream->buf, stream->len);
676  break;
677  case 16:
678  dsp_buffer_copy((static_cast<uint16_t *>(buf)), stream->buf, stream->len);
679  break;
680  case 32:
681  dsp_buffer_copy((static_cast<uint32_t *>(buf)), stream->buf, stream->len);
682  break;
683  case 64:
684  dsp_buffer_copy((static_cast<unsigned long *>(buf)), stream->buf, stream->len);
685  break;
686  case -32:
687  dsp_buffer_copy((static_cast<float *>(buf)), stream->buf, stream->len);
688  break;
689  case -64:
690  dsp_buffer_copy((static_cast<double *>(buf)), stream->buf, stream->len);
691  break;
692  default:
694  //Destroy the dsp stream
696  }
697 }
698 
700 {
701  void *buffer = malloc(stream->len * getBPS() / 8);
702  switch (getBPS())
703  {
704  case 8:
705  dsp_buffer_copy(stream->buf, (static_cast<uint8_t *>(buffer)), stream->len);
706  break;
707  case 16:
708  dsp_buffer_copy(stream->buf, (static_cast<uint16_t *>(buffer)), stream->len);
709  break;
710  case 32:
711  dsp_buffer_copy(stream->buf, (static_cast<uint32_t *>(buffer)), stream->len);
712  break;
713  case 64:
714  dsp_buffer_copy(stream->buf, (static_cast<unsigned long *>(buffer)), stream->len);
715  break;
716  case -32:
717  dsp_buffer_copy(stream->buf, (static_cast<float *>(buffer)), stream->len);
718  break;
719  case -64:
720  dsp_buffer_copy(stream->buf, (static_cast<double *>(buffer)), stream->len);
721  break;
722  default:
723  free (buffer);
724  break;
725  }
726  //Destroy the dsp stream
729  return static_cast<uint8_t *>(buffer);
730 }
731 }
MAXINDIDEVICE
#define MAXINDIDEVICE
Definition: indiapi.h:192
DSP::Interface::loadFITS
dsp_stream_p loadFITS(char *buf, int len)
loadFITS Converts FITS data into a dsp_stream structure pointer.
Definition: dspinterface.cpp:333
DSP::Interface::setBPS
void setBPS(int bps)
setBPS Set the returned file bit depth/sample size.
Definition: dspinterface.h:115
IP_RO
@ IP_RO
Definition: indiapi.h:183
indiutility.h
INDI::BaseDevice::getText
INDI::PropertyView< IText > * getText(const char *name) const
Definition: basedevice.cpp:104
DSP::Interface::ISNewBLOB
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
Definition: dspinterface.cpp:158
DSP::Interface::m_Name
const char * m_Name
Definition: dspinterface.h:173
fd
int fd
Definition: indiserver.c:117
_IBLOBVectorProperty::s
IPState s
Definition: indiapi.h:484
dsp_stream_new
DLL_EXPORT dsp_stream_p dsp_stream_new()
Allocate a new DSP stream type.
Definition: stream.c:48
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
DSP::Interface::Callback
virtual uint8_t * Callback(uint8_t *buf, uint32_t ndims, int *dims, int bits_per_sample)
Callback Called by processBLOB.
Definition: dspinterface.cpp:172
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
indicom.h
Implementations for common driver routines.
locale_compat.h
DSP::Interface::getStream
uint8_t * getStream()
Definition: dspinterface.cpp:699
INDI::Logger::DBG_WARNING
@ DBG_WARNING
Definition: indilogger.h:193
DSP::Interface::ActivateSP
ISwitchVectorProperty ActivateSP
Definition: dspinterface.h:158
MAXINDINAME
#define MAXINDINAME
Definition: indiapi.h:190
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
DSP::Interface::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Definition: dspinterface.cpp:148
INDI::BaseDevice::getNumber
INDI::PropertyView< INumber > * getNumber(const char *name) const
Definition: basedevice.cpp:99
INDI::Logger::DBG_ERROR
@ DBG_ERROR
Definition: indilogger.h:192
DSP::Interface::setStream
void setStream(void *buf, uint32_t dims, int *sizes, int bits_per_sample)
Definition: dspinterface.cpp:665
INDI_UNUSED
#define INDI_UNUSED(x)
Definition: indidevapi.h:799
DSP::Interface::Deactivated
virtual void Deactivated()
Deactivated Called after deactivation from client application.
Definition: dspinterface.cpp:226
DSP::Interface::ActivateS
ISwitch ActivateS[2]
Definition: dspinterface.h:159
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
IDSetBLOB
void void void void void void void void void IDSetBLOB(const IBLOBVectorProperty *b, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing BLOB vector property.
DSP::Interface::FitsB
IBLOB FitsB
Definition: dspinterface.h:156
DSP::Interface::getBPS
int getBPS()
getBPS Get the returned file bit depth/sample size.
Definition: dspinterface.h:121
dspinterface.h
dsp_stream_free
DLL_EXPORT void dsp_stream_free(dsp_stream_p stream)
Free the DSP stream passed as argument.
Definition: stream.c:76
INDI::BaseDevice::getSwitch
INDI::PropertyView< ISwitch > * getSwitch(const char *name) const
Definition: basedevice.cpp:109
MAXINDIMESSAGE
#define MAXINDIMESSAGE
Definition: indiapi.h:197
DEBUG
#define DEBUG(priority, msg)
Macro to print log messages. Example of usage of the Logger: DEBUG(DBG_DEBUG, "hello " << "world");.
Definition: indilogger.h:56
dsp_stream_t
Contains a set of informations and data relative to a buffer and how to use it.
Definition: dsp.h:175
INDI::ObservedToJ2000
void ObservedToJ2000(IEquatorialCoordinates *observed, double jd, IEquatorialCoordinates *J2000pos)
ObservedToJ2000 converts an observed position to a J2000 catalogue position removes aberration,...
Definition: libastro.cpp:50
INDI::Logger::DBG_DEBUG
@ DBG_DEBUG
Definition: indilogger.h:195
indilogger.h
INDI::mkpath
int mkpath(std::string s, mode_t mode)
Create a path directory - this function uses 'mkdir'.
Definition: indiutility.cpp:29
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
type
__le16 type
Definition: pwc-ioctl.h:2
DSP::Interface::PluginActive
bool PluginActive
Definition: dspinterface.h:153
INDI::IEquatorialCoordinates::rightascension
double rightascension
Definition: libastro.h:50
_INumberVectorProperty
Number vector property descriptor.
Definition: indiapi.h:317
DSP::Interface::Interface
Interface(INDI::DefaultDevice *dev, Type type=DSP_NONE, const char *name="DSP_PLUGIN", const char *label="DSP Plugin")
Definition: dspinterface.cpp:60
DSP::Interface::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Definition: dspinterface.cpp:138
IUFillSwitchVector
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:412
DSP::Interface::stream
dsp_stream_p stream
Definition: dspinterface.h:178
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
_INumberVectorProperty::np
INumber * np
Definition: indiapi.h:334
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
dsp_stream_t::len
int len
The buffers length.
Definition: dsp.h:178
dsp_buffer_copy
#define dsp_buffer_copy(in, out, len)
Fill the output buffer with the values of the elements of the input stream by casting them to the out...
Definition: dsp.h:791
DSP::Interface::m_Label
const char * m_Label
Definition: dspinterface.h:174
defaultdevice.h
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
end
JsonIterator end(JsonValue)
Definition: gason.h:108
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
MAXINDIFORMAT
#define MAXINDIFORMAT
Definition: indiapi.h:194
IUFillBLOB
void IUFillBLOB(IBLOB *bp, const char *name, const char *label, const char *format)
Assign attributes for a BLOB property. The BLOB's data and auxiliary elements will be set to NULL.
Definition: indidriver.c:390
dsp_stream_free_buffer
DLL_EXPORT void dsp_stream_free_buffer(dsp_stream_p stream)
Free the buffer of the DSP Stream passed as argument.
Definition: stream.c:41
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
DSP::DSP_TAB
const char * DSP_TAB
Definition: dspinterface.cpp:58
DSP::Interface::Activated
virtual void Activated()
Activated Called after activation from client application.
Definition: dspinterface.cpp:221
DSP
The DSP Namespace adds signal processing to INDI drivers. Primarily written for sensors and detectors...
Definition: convolution.cpp:39
dsp_stream_alloc_buffer
DLL_EXPORT void dsp_stream_alloc_buffer(dsp_stream_p stream, int len)
Allocate a buffer with length len on the stream passed as argument.
Definition: stream.c:21
Type
The Interface class is the base class for the DSP plugins of INDI.
name
const char * name
Definition: indiserver.c:116
indisensorinterface.h
DSP::Interface::setSizes
void setSizes(uint32_t num, int *sizes)
setSizes Set the returned file dimensions and corresponding sizes.
Definition: dspinterface.h:102
DSP::Interface::FitsBP
IBLOBVectorProperty FitsBP
Definition: dspinterface.h:155
_IBLOBVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:474
DEBUGF
#define DEBUGF(priority, msg,...)
Definition: indilogger.h:57
fs_sexa
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string.
Definition: indicom.c:137
indiccd.h
IP_RW
@ IP_RW
Definition: indiapi.h:185
MAXINDILABEL
#define MAXINDILABEL
Definition: indiapi.h:191
DSP::Interface::saveConfigItems
virtual bool saveConfigItems(FILE *fp)
Definition: dspinterface.cpp:231
DSP::Interface::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Definition: dspinterface.cpp:118
DSP::Interface::updateProperties
virtual bool updateProperties()
Definition: dspinterface.cpp:103
ISState
ISState
Switch state.
Definition: indiapi.h:148
_ISwitchVectorProperty::sp
ISwitch * sp
Definition: indiapi.h:384
DSP::Interface::ISGetProperties
virtual void ISGetProperties(const char *dev)
Definition: dspinterface.cpp:88
INDI::IEquatorialCoordinates
Definition: libastro.h:48
dsp_stream_add_dim
DLL_EXPORT void dsp_stream_add_dim(dsp_stream_p stream, int len)
Add a dimension with length len to a DSP stream.
Definition: stream.c:111
INDI::DefaultDevice
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
Definition: defaultdevice.h:118
IUFillBLOBVector
void IUFillBLOBVector(IBLOBVectorProperty *bvp, IBLOB *bp, int nbp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a BLOB vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:499
DSP::Interface::~Interface
virtual ~Interface()
Definition: dspinterface.cpp:79
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
IDSetSwitch
void void void void void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing switch vector property.
DSP::Interface::processBLOB
bool processBLOB(uint8_t *buf, uint32_t ndims, int *dims, int bits_per_sample)
processBLOB Propagate to Callback and generate BLOBs for parent device.
Definition: dspinterface.cpp:182
errno
int errno
IUFillSwitch
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition: indidriver.c:320
Aux::buffer
std::vector< uint8_t > buffer
Definition: celestronauxpacket.h:38
dsp_stream_t::buf
dsp_t * buf
buffer
Definition: dsp.h:184
DSP::Interface::m_Device
INDI::DefaultDevice * m_Device
Definition: dspinterface.h:172
libastro.h
DSP::Interface::getDeviceName
const char * getDeviceName()
Definition: dspinterface.cpp:83
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151