source: BAORadio/libindi/libindi/drivers/video/v4ldriver.cpp @ 642

Last change on this file since 642 was 642, checked in by frichard, 12 years ago

-Alignement des antennes
-Version 0.0.9 de libindi

File size: 23.5 KB
Line 
1#if 0
2    V4L INDI Driver
3    INDI Interface for V4L devices
4    Copyright (C) 2003-2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
20#endif
21
22#include "v4ldriver.h"
23
24V4L_Driver::V4L_Driver()
25{
26  allocateBuffers();
27
28  camNameT[0].text  = NULL; 
29  PortT[0].text     = NULL;
30  IUSaveText(&PortT[0], "/dev/video0");
31
32  divider = 128.;
33}
34
35V4L_Driver::~V4L_Driver()
36{
37  releaseBuffers();
38}
39
40
41void V4L_Driver::initProperties(const char *dev)
42{
43 
44  strncpy(device_name, dev, MAXINDIDEVICE);
45 
46  /* Connection */
47  IUFillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
48  IUFillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
49  IUFillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), dev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
50
51 /* Port */
52  IUFillText(&PortT[0], "PORT", "Port", "/dev/video0");
53  IUFillTextVector(&PortTP, PortT, NARRAY(PortT), dev, "DEVICE_PORT", "Ports", COMM_GROUP, IP_RW, 0, IPS_IDLE);
54
55 /* Video Stream */
56  IUFillSwitch(&StreamS[0], "ON", "Stream On", ISS_OFF);
57  IUFillSwitch(&StreamS[1], "OFF", "Stream Off", ISS_ON);
58  IUFillSwitchVector(&StreamSP, StreamS, NARRAY(StreamS), dev, "VIDEO_STREAM", "Video Stream", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
59
60  /* Compression */
61  IUFillSwitch(&CompressS[0], "ON", "", ISS_ON);
62  IUFillSwitch(&CompressS[1], "OFF", "", ISS_OFF);
63  IUFillSwitchVector(&CompressSP, CompressS, NARRAY(StreamS), dev, "Compression", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
64
65  /* Image type */
66  IUFillSwitch(&ImageTypeS[0], "Grey", "", ISS_ON);
67  IUFillSwitch(&ImageTypeS[1], "Color", "", ISS_OFF);
68  IUFillSwitchVector(&ImageTypeSP, ImageTypeS, NARRAY(ImageTypeS), dev, "Image Type", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
69
70  /* Camera Name */
71  IUFillText(&camNameT[0], "Model", "", "");
72  IUFillTextVector(&camNameTP, camNameT, NARRAY(camNameT), dev, "Camera Model", "", COMM_GROUP, IP_RO, 0, IPS_IDLE);
73 
74  /* Expose */
75  IUFillNumber(&ExposeTimeN[0], "CCD_EXPOSURE_VALUE", "Duration (s)", "%5.2f", 0., 36000., 0.5, 1.);
76  IUFillNumberVector(&ExposeTimeNP, ExposeTimeN, NARRAY(ExposeTimeN), dev, "CCD_EXPOSURE", "Expose", COMM_GROUP, IP_RW, 60, IPS_IDLE);
77
78/* Frame Rate */
79  IUFillNumber(&FrameRateN[0], "RATE", "Rate", "%0.f", 1., 50., 1., 10.);
80  IUFillNumberVector(&FrameRateNP, FrameRateN, NARRAY(FrameRateN), dev, "FRAME_RATE", "Frame Rate", COMM_GROUP, IP_RW, 60, IPS_IDLE);
81
82  /* Frame dimension */
83  IUFillNumber(&FrameN[0], "X", "X", "%.0f", 0., 0., 0., 0.);
84  IUFillNumber(&FrameN[1], "Y", "Y", "%.0f", 0., 0., 0., 0.);
85  IUFillNumber(&FrameN[2], "WIDTH", "Width", "%.0f", 0., 0., 10., 0.);
86  IUFillNumber(&FrameN[3], "HEIGHT", "Height", "%.0f", 0., 0., 10., 0.);
87  IUFillNumberVector(&FrameNP, FrameN, NARRAY(FrameN), dev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
88
89  /*IUFillNumber(&ImageSizeN[0], "WIDTH", "Width", "%0.f", 0., 0., 10., 0.);
90  IUFillNumber(&ImageSizeN[1], "HEIGHT", "Height", "%0.f", 0., 0., 10., 0.);
91  IUFillNumberVector(&ImageSizeNP, ImageSizeN, NARRAY(ImageSizeN), dev, "IMAGE_SIZE", "Image Size", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);*/
92 
93  #ifndef HAVE_LINUX_VIDEODEV2_H
94  IUFillNumber(&ImageAdjustN[0], "Contrast", "", "%0.f", 0., 256., 1., 0.);
95  IUFillNumber(&ImageAdjustN[1], "Brightness", "", "%0.f", 0., 256., 1., 0.);
96  IUFillNumber(&ImageAdjustN[2], "Hue", "", "%0.f", 0., 256., 1., 0.);
97  IUFillNumber(&ImageAdjustN[3], "Color", "", "%0.f", 0., 256., 1., 0.);
98  IUFillNumber(&ImageAdjustN[4], "Whiteness", "", "%0.f", 0., 256., 1., 0.);
99  IUFillNumberVector(&ImageAdjustNP, ImageAdjustN, NARRAY(ImageAdjustN), dev, "Image Adjustments", "", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
100  #else
101  IUFillNumberVector(&ImageAdjustNP, NULL, 0, dev, "Image Adjustments", "", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
102  #endif
103
104  // We need to setup the BLOB (Binary Large Object) below. Using this property, we can send FITS to our client
105  strcpy(imageB.name, "CCD1");
106  strcpy(imageB.label, "Feed");
107  strcpy(imageB.format, "");
108  imageB.blob    = 0;
109  imageB.bloblen = 0;
110  imageB.size    = 0;
111  imageB.bvp     = 0;
112  imageB.aux0    = 0;
113  imageB.aux1    = 0;
114  imageB.aux2    = 0;
115 
116  strcpy(imageBP.device, dev);
117  strcpy(imageBP.name, "Video");
118  strcpy(imageBP.label, "Video");
119  strcpy(imageBP.group, COMM_GROUP);
120  strcpy(imageBP.timestamp, "");
121  imageBP.p       = IP_RO;
122  imageBP.timeout = 0;
123  imageBP.s       = IPS_IDLE;
124  imageBP.bp      = &imageB;
125  imageBP.nbp     = 1;
126  imageBP.aux     = 0;
127
128}
129
130void V4L_Driver::initCamBase()
131{
132   #ifndef HAVE_LINUX_VIDEODEV2_H
133    v4l_base = new V4L1_Base();
134   #else
135    v4l_base = new V4L2_Base();
136   #endif
137}
138
139void V4L_Driver::ISGetProperties (const char *dev)
140{ 
141
142  if (dev && strcmp (device_name, dev))
143    return;
144
145  /* COMM_GROUP */
146  IDDefSwitch(&PowerSP, NULL);
147  IDDefText(&PortTP, NULL);
148  IDDefText(&camNameTP, NULL);
149  IDDefSwitch(&StreamSP, NULL);
150  #ifndef HAVE_LINUX_VIDEODEV2_H
151  IDDefNumber(&FrameRateNP, NULL);
152  #endif
153  IDDefNumber(&ExposeTimeNP, NULL);
154  IDDefBLOB(&imageBP, NULL);
155 
156  /* Image properties */
157  IDDefSwitch(&CompressSP, NULL);
158  IDDefSwitch(&ImageTypeSP, NULL);
159  IDDefNumber(&FrameNP, NULL);
160 
161  #ifndef HAVE_LINUX_VIDEODEV2_H
162  IDDefNumber(&ImageAdjustNP, NULL);
163  #endif
164
165
166 
167}
168 
169void V4L_Driver::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
170{
171        char errmsg[ERRMSGSIZ];
172
173        /* ignore if not ours */
174        if (dev && strcmp (device_name, dev))
175            return;
176           
177     /* Connection */
178     if (!strcmp (name, PowerSP.name))
179     {
180          IUResetSwitch(&PowerSP);
181          IUUpdateSwitch(&PowerSP, states, names, n);
182          connectCamera();
183          return;
184     }
185
186     /* Compression */
187     if (!strcmp(name, CompressSP.name))
188     {
189       IUResetSwitch(&CompressSP);
190       IUUpdateSwitch(&CompressSP, states, names, n);
191       CompressSP.s = IPS_OK;
192       
193       IDSetSwitch(&CompressSP, NULL);
194       return;
195     }   
196
197     /* Image Type */
198     if (!strcmp(name, ImageTypeSP.name))
199     {
200       IUResetSwitch(&ImageTypeSP);
201       IUUpdateSwitch(&ImageTypeSP, states, names, n);
202       ImageTypeSP.s = IPS_OK;
203       
204       IDSetSwitch(&ImageTypeSP, NULL);
205       return;
206     }
207     
208     /* Video Stream */
209     if (!strcmp(name, StreamSP.name))
210     {
211     
212      if (checkPowerS(&StreamSP))
213         return;
214       
215       IUResetSwitch(&StreamSP);
216       IUUpdateSwitch(&StreamSP, states, names, n);
217       StreamSP.s = IPS_IDLE;
218       
219         
220       if (StreamS[0].s == ISS_ON)
221       {
222         frameCount = 0;
223         IDLog("Starting the video stream.\n");
224         StreamSP.= IPS_BUSY; 
225         v4l_base->start_capturing(errmsg);
226       }
227       else
228       {
229         IDLog("The video stream has been disabled. Frame count %d\n", frameCount);
230         v4l_base->stop_capturing(errmsg);
231       }
232       
233       IDSetSwitch(&StreamSP, NULL);
234       return;
235     }
236     
237}
238
239void V4L_Driver::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int /*n*/)
240{
241        IText *tp;
242
243
244       /* ignore if not ours */ 
245       if (dev && strcmp (device_name, dev))
246         return;
247
248        if (!strcmp(name, PortTP.name) )
249        {
250          PortTP.s = IPS_OK;
251          tp = IUFindText( &PortTP, names[0] );
252          if (!tp)
253           return;
254
255          IUSaveText(tp, texts[0]);
256          IDSetText (&PortTP, NULL);
257          return;
258        }
259}
260
261void V4L_Driver::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
262{
263      char errmsg[ERRMSGSIZ];
264
265        /* ignore if not ours */
266        if (dev && strcmp (device_name, dev))
267            return;
268           
269   
270    /* Frame Size */
271    if (!strcmp (FrameNP.name, name))
272    {
273      if (checkPowerN(&FrameNP))
274        return;
275       
276       int oldW = (int) FrameN[2].value;
277       int oldH = (int) FrameN[3].value;
278
279      FrameNP.s = IPS_OK;
280     
281      if (IUUpdateNumber(&FrameNP, values, names, n) < 0)
282       return;
283     
284      if (v4l_base->setSize( (int) FrameN[2].value, (int) FrameN[3].value) != -1)
285      {
286         FrameN[2].value = v4l_base->getWidth();
287         FrameN[3].value = v4l_base->getHeight();
288         V4LFrame->width = (int) FrameN[2].value;
289         V4LFrame->height= (int) FrameN[3].value;
290         IDSetNumber(&FrameNP, NULL);
291         return;
292      }
293      else
294      {
295        FrameN[2].value = oldW;
296        FrameN[3].value = oldH;
297        FrameNP.s = IPS_ALERT;
298        IDSetNumber(&FrameNP, "Failed to set a new image size.");
299      }
300     
301      return;
302   }
303
304   #ifndef HAVE_LINUX_VIDEODEV2_H
305   /* Frame rate */
306   if (!strcmp (FrameRateNP.name, name))
307   {
308     if (checkPowerN(&FrameRateNP))
309      return;
310     
311     FrameRateNP.s = IPS_IDLE;
312     
313     if (IUUpdateNumber(&FrameRateNP, values, names, n) < 0)
314       return;
315       
316     v4l_base->setFPS( (int) FrameRateN[0].value );
317     
318     FrameRateNP.s = IPS_OK;
319     IDSetNumber(&FrameRateNP, NULL);
320     return;
321   }
322   #endif
323   
324   
325   if (!strcmp (ImageAdjustNP.name, name))
326   {
327     if (checkPowerN(&ImageAdjustNP))
328       return;
329       
330     ImageAdjustNP.s = IPS_IDLE;
331     
332     if (IUUpdateNumber(&ImageAdjustNP, values, names, n) < 0)
333       return;
334     
335     #ifndef HAVE_LINUX_VIDEODEV2_H
336     v4l_base->setContrast( (int) (ImageAdjustN[0].value * divider));
337     v4l_base->setBrightness( (int) (ImageAdjustN[1].value * divider));
338     v4l_base->setHue( (int) (ImageAdjustN[2].value * divider));
339     v4l_base->setColor( (int) (ImageAdjustN[3].value * divider));
340     v4l_base->setWhiteness( (int) (ImageAdjustN[4].value * divider));
341     
342     ImageAdjustN[0].value = v4l_base->getContrast() / divider;
343     ImageAdjustN[1].value = v4l_base->getBrightness() / divider;
344     ImageAdjustN[2].value = v4l_base->getHue() / divider;
345     ImageAdjustN[3].value = v4l_base->getColor() / divider;
346     ImageAdjustN[4].value = v4l_base->getWhiteness() / divider;
347
348     #else
349     unsigned int ctrl_id;
350     for (int i=0; i < ImageAdjustNP.nnp; i++)
351     {
352         ctrl_id = *((unsigned int *) ImageAdjustNP.np[i].aux0);
353         if (v4l_base->setINTControl( ctrl_id , ImageAdjustNP.np[i].value, errmsg) < 0)
354         {
355            ImageAdjustNP.s = IPS_ALERT;
356            IDSetNumber(&ImageAdjustNP, "Unable to adjust setting. %s", errmsg);
357            return;
358         }
359     }
360     #endif
361     
362     ImageAdjustNP.s = IPS_OK;
363     IDSetNumber(&ImageAdjustNP, NULL);
364     return;
365   }
366   
367   
368    /* Exposure */
369    if (!strcmp (ExposeTimeNP.name, name))
370    {
371       
372       if (checkPowerN(&ExposeTimeNP))
373         return;
374   
375        if (StreamS[0].s == ISS_ON) 
376          v4l_base->stop_capturing(errmsg);
377
378        StreamS[0].= ISS_OFF;
379        StreamS[1].= ISS_ON;
380        StreamSP.s    = IPS_IDLE;
381        IDSetSwitch(&StreamSP, NULL);
382       
383        V4LFrame->expose = 1000;
384
385        ExposeTimeNP.s   = IPS_BUSY;
386        IDSetNumber(&ExposeTimeNP, NULL);
387
388        time(&capture_start);
389        v4l_base->start_capturing(errmsg);
390       
391        return;
392    } 
393     
394 
395       
396}
397
398void V4L_Driver::newFrame(void *p)
399{
400  ((V4L_Driver *) (p))->updateFrame();
401}
402
403void V4L_Driver::updateFrame()
404{
405  char errmsg[ERRMSGSIZ];
406  static const unsigned int FRAME_DROP = 2;
407  static int dropLarge = FRAME_DROP;
408
409  if (StreamSP.s == IPS_BUSY)
410  {
411        // Ad hoc way of dropping frames
412        frameCount++;
413        dropLarge--;
414        if (dropLarge == 0)
415        {
416          dropLarge = (int) (((ImageTypeS[0].s == ISS_ON) ? FRAME_DROP : FRAME_DROP*3) * (FrameN[2].value / 160.0));
417          updateStream();
418          return;
419        }
420  }
421  else if (ExposeTimeNP.s == IPS_BUSY)
422  {
423     V4LFrame->Y      = v4l_base->getY();
424     v4l_base->stop_capturing(errmsg);
425     time(&capture_end);
426     IDLog("Capture of ONE frame took %g seconds.\n", difftime(capture_end, capture_start));
427     grabImage();
428  }
429
430}
431
432void V4L_Driver::updateStream()
433{
434 
435   int width  = v4l_base->getWidth();
436   int height = v4l_base->getHeight();
437   uLongf compressedBytes = 0;
438   uLong totalBytes;
439   unsigned char *targetFrame;
440   int r;
441   
442   if (PowerS[0].s == ISS_OFF || StreamS[0].s == ISS_OFF) return;
443   
444   if (ImageTypeS[0].s == ISS_ON)
445      V4LFrame->Y               = v4l_base->getY();
446   else
447      V4LFrame->colorBuffer     = v4l_base->getColorBuffer();
448 
449   totalBytes  = ImageTypeS[0].s == ISS_ON ? width * height : width * height * 4;
450   targetFrame = ImageTypeS[0].s == ISS_ON ? V4LFrame->Y : V4LFrame->colorBuffer;
451
452   /* Do we want to compress ? */
453    if (CompressS[0].s == ISS_ON)
454    {   
455        /* Compress frame */
456        V4LFrame->compressedFrame = (unsigned char *) realloc (V4LFrame->compressedFrame, sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
457   
458        compressedBytes = sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3;
459   
460        r = compress2(V4LFrame->compressedFrame, &compressedBytes, targetFrame, totalBytes, 4);
461        if (r != Z_OK)
462        {
463                /* this should NEVER happen */
464                IDLog("internal error - compression failed: %d\n", r);
465                return;
466        }
467   
468        /* #3.A Send it compressed */
469        imageB.blob = V4LFrame->compressedFrame;
470        imageB.bloblen = compressedBytes;
471        imageB.size = totalBytes;
472        strcpy(imageB.format, ".stream.z");
473     }
474     else
475     {
476       /* #3.B Send it uncompressed */
477        imageB.blob = targetFrame;
478        imageB.bloblen = totalBytes;
479        imageB.size = totalBytes;
480        strcpy(imageB.format, ".stream");
481     }
482       
483   imageBP.s = IPS_OK;
484   IDSetBLOB (&imageBP, NULL);
485   
486   #ifndef HAVE_LINUX_VIDEODEV2_H
487      char errmsg[ERRMSGSIZ];
488      v4l_base->start_capturing(errmsg);
489   #endif
490}
491
492/* Downloads the image from the CCD row by row and store them
493   in a raw file.
494 N.B. No processing is done on the image */
495int V4L_Driver::grabImage()
496{
497   int err, fd;
498   char errmsg[ERRMSG_SIZE];
499   char temp_filename[TEMPFILE_LEN] = "/tmp/fitsXXXXXX";
500   
501   
502   if ((fd = mkstemp(temp_filename)) < 0)
503   { 
504    IDMessage(device_name, "Error making temporary filename.");
505    IDLog("Error making temporary filename.\n");
506    return -1;
507   }
508   close(fd);
509 
510   
511   err = writeFITS(temp_filename, errmsg);
512   if (err)
513   {
514       IDMessage(device_name, errmsg, NULL);
515       return -1;
516   }
517   
518  return 0;
519}
520
521int V4L_Driver::writeFITS(const char * filename, char errmsg[])
522{
523    fitsfile *fptr;       /* pointer to the FITS file; defined in fitsio.h */
524    int status;
525    long  fpixel = 1, naxis = 2, nelements;
526    long naxes[2];
527    char filename_rw[TEMPFILE_LEN+1];
528
529    INDI_UNUSED(errmsg);
530
531    // Append ! to file name to over write it.
532    snprintf(filename_rw, TEMPFILE_LEN+1, "!%s", filename);
533
534    naxes[0] = v4l_base->getWidth();
535    naxes[1] = v4l_base->getHeight();
536
537    status = 0;         /* initialize status before calling fitsio routines */
538    fits_create_file(&fptr, filename_rw, &status);   /* create new file */
539
540    /* Create the primary array image (16-bit short integer pixels */
541    fits_create_img(fptr, BYTE_IMG, naxis, naxes, &status);
542
543    addFITSKeywords(fptr);
544
545    nelements = naxes[0] * naxes[1];          /* number of pixels to write */
546
547    /* Write the array of integers to the image */
548    fits_write_img(fptr, TBYTE, fpixel, nelements, V4LFrame->Y, &status);
549
550    fits_close_file(fptr, &status);            /* close the file */
551
552    fits_report_error(stderr, status);  /* print out any error messages */
553
554    /* Success */
555    ExposeTimeNP.s = IPS_OK;
556    IDSetNumber(&ExposeTimeNP, NULL);
557    uploadFile(filename);
558    unlink(filename);
559
560    return status;
561}
562
563void V4L_Driver::addFITSKeywords(fitsfile *fptr)
564{
565  int status=0; 
566
567  char keyname[32], comment[64];
568
569 strncpy(keyname, "EXPOSURE", 32);
570 strncpy(comment, "Total Exposure Time (ms)", 64);
571 fits_update_key(fptr, TLONG, keyname , &(V4LFrame->expose), comment, &status);
572
573 strncpy(keyname, "INSTRUME", 32);
574 strncpy(comment, "Webcam Name", 64);
575 fits_update_key(fptr, TSTRING, keyname, v4l_base->getDeviceName(), comment, &status);
576
577 fits_write_date(fptr, &status);
578}
579
580void V4L_Driver::uploadFile(const char * filename)
581{
582   
583   FILE * fitsFile;
584   int r=0;
585   unsigned int nr = 0;
586   uLong  totalBytes;
587   uLongf compressedBytes = 0;
588   struct stat stat_p; 
589 
590   if ( -1 ==  stat (filename, &stat_p))
591   { 
592     IDLog(" Error occurred attempting to stat %s\n", filename); 
593     return; 
594   }
595   
596   totalBytes = stat_p.st_size;
597
598   fitsFile = fopen(filename, "r");
599   
600   if (fitsFile == NULL)
601    return;
602   
603   fitsData = (fitsData == NULL) ? (unsigned char *) malloc(sizeof(unsigned char) * totalBytes) :
604                                   (unsigned char *) realloc(fitsData, sizeof(unsigned char) * totalBytes);
605   /* #1 Read file from disk */ 
606   for (unsigned int i=0; i < totalBytes; i+= nr)
607   {
608      nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
609     
610     if (nr <= 0)
611     {
612        IDLog("Error reading temporary FITS file.\n");
613        return;
614     }
615   }
616   fclose(fitsFile);
617   
618   if (CompressS[0].s == ISS_ON)
619   {   
620   /* #2 Compress it */
621   V4LFrame->compressedFrame = (unsigned char *) realloc (V4LFrame->compressedFrame, sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
622   
623    compressedBytes = sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3;
624     
625     
626   r = compress2(V4LFrame->compressedFrame, &compressedBytes, fitsData, totalBytes, 9);
627   if (r != Z_OK)
628   {
629        /* this should NEVER happen */
630        IDLog("internal error - compression failed: %d\n", r);
631        return;
632   }
633
634   /* #3.A Send it compressed */
635   imageB.blob = V4LFrame->compressedFrame;
636   imageB.bloblen = compressedBytes;
637   imageB.size = totalBytes;
638   strcpy(imageB.format, ".fits.z");
639   }
640   else
641   {
642     imageB.blob = fitsData;
643     imageB.bloblen = totalBytes;
644     imageB.size = totalBytes;
645     strcpy(imageB.format, ".fits");
646   }
647   
648   imageBP.s = IPS_OK;
649   IDSetBLOB (&imageBP, NULL);
650   
651} 
652
653void V4L_Driver::connectCamera()
654{
655  char errmsg[ERRMSGSIZ];
656 
657   
658  switch (PowerS[0].s)
659  {
660     case ISS_ON:
661      if (v4l_base->connectCam(PortT[0].text, errmsg) < 0)
662      {
663          PowerSP.s = IPS_IDLE;
664          PowerS[0].s = ISS_OFF;
665          PowerS[1].s = ISS_ON;
666          IDSetSwitch(&PowerSP, "Error: unable to open device");
667          IDLog("Error: %s\n", errmsg);
668          return;
669      }
670     
671      /* Sucess! */
672      PowerS[0].s = ISS_ON;
673      PowerS[1].s = ISS_OFF;
674      PowerSP.s = IPS_OK;
675      IDSetSwitch(&PowerSP, "Video4Linux Generic Device is online. Retrieving basic data.");
676
677      v4l_base->registerCallback(newFrame, this);
678     
679      IDLog("V4L Device is online. Retrieving basic data.\n");
680      getBasicData();
681     
682      break;
683     
684    case ISS_OFF:
685      PowerS[0].s = ISS_OFF;
686      PowerS[1].s = ISS_ON;
687      PowerSP.s = IPS_IDLE;
688     
689      v4l_base->disconnectCam();
690     
691      IDSetSwitch(&PowerSP, "Video4Linux Generic Device is offline.");
692     
693      break;
694     }
695}
696
697/* Retrieves basic data from the device upon connection.*/
698void V4L_Driver::getBasicData()
699{
700
701  int xmax, ymax, xmin, ymin;
702 
703  v4l_base->getMaxMinSize(xmax, ymax, xmin, ymin);
704
705  /* Width */
706  FrameN[2].value = v4l_base->getWidth();
707  FrameN[2].min = xmin;
708  FrameN[2].max = xmax;
709  V4LFrame->width = (int) FrameN[2].value;
710 
711  /* Height */
712  FrameN[3].value = v4l_base->getHeight();
713  FrameN[3].min = ymin;
714  FrameN[3].max = ymax;
715  V4LFrame->height = (int) FrameN[3].value;
716 
717  IUUpdateMinMax(&FrameNP);
718  IDSetNumber(&FrameNP, NULL);
719 
720  IUSaveText(&camNameT[0], v4l_base->getDeviceName());
721  IDSetText(&camNameTP, NULL);
722
723   #ifndef HAVE_LINUX_VIDEODEV2_H
724     updateV4L1Controls();
725   #else
726    updateV4L2Controls();
727   #endif
728   
729}
730
731#ifdef HAVE_LINUX_VIDEODEV2_H
732void V4L_Driver::updateV4L2Controls()
733{
734    // #1 Query for INTEGER controls, and fill up the structure
735      free(ImageAdjustNP.np);
736      ImageAdjustNP.nnp = 0;
737     
738   if (v4l_base->queryINTControls(&ImageAdjustNP) > 0)
739      IDDefNumber(&ImageAdjustNP, NULL);
740}
741#else
742void V4L_Driver::updateV4L1Controls()
743{
744
745  if ( (v4l_base->getContrast() / divider) > ImageAdjustN[0].max)
746      divider *=2;
747
748  if ( (v4l_base->getHue() / divider) > ImageAdjustN[2].max)
749      divider *=2;
750
751  ImageAdjustN[0].value = v4l_base->getContrast() / divider;
752  ImageAdjustN[1].value = v4l_base->getBrightness() / divider;
753  ImageAdjustN[2].value = v4l_base->getHue() / divider;
754  ImageAdjustN[3].value = v4l_base->getColor() / divider;
755  ImageAdjustN[4].value = v4l_base->getWhiteness() / divider;
756
757  ImageAdjustNP.s = IPS_OK;
758  IDSetNumber(&ImageAdjustNP, NULL);
759 
760}
761#endif
762
763int V4L_Driver::checkPowerS(ISwitchVectorProperty *sp)
764{
765  if (PowerSP.s != IPS_OK)
766  {
767    if (!strcmp(sp->label, ""))
768        IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->name);
769    else
770        IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->label);
771   
772    sp->s = IPS_IDLE;
773    IDSetSwitch(sp, NULL);
774    return -1;
775  }
776
777  return 0;
778}
779
780int V4L_Driver::checkPowerN(INumberVectorProperty *np)
781{
782   
783  if (PowerSP.s != IPS_OK)
784  {
785    if (!strcmp(np->label, ""))
786        IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->name);
787    else
788        IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->label);
789       
790    np->s = IPS_IDLE;
791    IDSetNumber(np, NULL);
792    return -1;
793  }
794
795  return 0;
796}
797
798int V4L_Driver::checkPowerT(ITextVectorProperty *tp)
799{
800
801  if (PowerSP.s != IPS_OK)
802  {
803    if (!strcmp(tp->label, ""))
804        IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->name);
805    else
806        IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->label);
807       
808    tp->s = IPS_IDLE;
809    IDSetText(tp, NULL);
810    return -1;
811  }
812
813  return 0;
814
815}
816
817void V4L_Driver::allocateBuffers()
818{
819     V4LFrame = (img_t *) malloc (sizeof(img_t));
820 
821     if (V4LFrame == NULL)
822     {
823       IDMessage(NULL, "Error: unable to initialize driver. Low memory.");
824       IDLog("Error: unable to initialize driver. Low memory.");
825       exit(-1);
826     }
827
828     fitsData                   = (unsigned char *) malloc (sizeof(unsigned char) * 1);
829     V4LFrame->Y                = (unsigned char *) malloc (sizeof(unsigned char) * 1);
830     V4LFrame->U                = (unsigned char *) malloc (sizeof(unsigned char) * 1);
831     V4LFrame->V                = (unsigned char *) malloc (sizeof(unsigned char) * 1);
832     V4LFrame->colorBuffer      = (unsigned char *) malloc (sizeof(unsigned char) * 1);
833     V4LFrame->compressedFrame  = (unsigned char *) malloc (sizeof(unsigned char) * 1);
834}
835
836void V4L_Driver::releaseBuffers()
837{
838  free(fitsData);
839  free(V4LFrame->Y);
840  free(V4LFrame->U);
841  free(V4LFrame->V);
842  free(V4LFrame->colorBuffer);
843  free(V4LFrame->compressedFrame);
844  free (V4LFrame);
845}
846
847
Note: See TracBrowser for help on using the repository browser.