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

Last change on this file since 490 was 490, checked in by campagne, 14 years ago

import libindi (JEC)

File size: 23.3 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 fits_update_key(fptr, TLONG, "EXPOSURE", &(V4LFrame->expose), "Total Exposure Time (ms)", &status); 
568 fits_update_key(fptr, TSTRING, "INSTRUME", v4l_base->getDeviceName(), "Webcam Name", &status);
569 fits_write_date(fptr, &status);
570}
571
572void V4L_Driver::uploadFile(const char * filename)
573{
574   
575   FILE * fitsFile;
576   int r=0;
577   unsigned int nr = 0;
578   uLong  totalBytes;
579   uLongf compressedBytes = 0;
580   struct stat stat_p; 
581 
582   if ( -1 ==  stat (filename, &stat_p))
583   { 
584     IDLog(" Error occurred attempting to stat %s\n", filename); 
585     return; 
586   }
587   
588   totalBytes = stat_p.st_size;
589
590   fitsFile = fopen(filename, "r");
591   
592   if (fitsFile == NULL)
593    return;
594   
595   fitsData = (fitsData == NULL) ? (unsigned char *) malloc(sizeof(unsigned char) * totalBytes) :
596                                   (unsigned char *) realloc(fitsData, sizeof(unsigned char) * totalBytes);
597   /* #1 Read file from disk */ 
598   for (unsigned int i=0; i < totalBytes; i+= nr)
599   {
600      nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
601     
602     if (nr <= 0)
603     {
604        IDLog("Error reading temporary FITS file.\n");
605        return;
606     }
607   }
608   fclose(fitsFile);
609   
610   if (CompressS[0].s == ISS_ON)
611   {   
612   /* #2 Compress it */
613   V4LFrame->compressedFrame = (unsigned char *) realloc (V4LFrame->compressedFrame, sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
614   
615    compressedBytes = sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3;
616     
617     
618   r = compress2(V4LFrame->compressedFrame, &compressedBytes, fitsData, totalBytes, 9);
619   if (r != Z_OK)
620   {
621        /* this should NEVER happen */
622        IDLog("internal error - compression failed: %d\n", r);
623        return;
624   }
625
626   /* #3.A Send it compressed */
627   imageB.blob = V4LFrame->compressedFrame;
628   imageB.bloblen = compressedBytes;
629   imageB.size = totalBytes;
630   strcpy(imageB.format, ".fits.z");
631   }
632   else
633   {
634     imageB.blob = fitsData;
635     imageB.bloblen = totalBytes;
636     imageB.size = totalBytes;
637     strcpy(imageB.format, ".fits");
638   }
639   
640   imageBP.s = IPS_OK;
641   IDSetBLOB (&imageBP, NULL);
642   
643} 
644
645void V4L_Driver::connectCamera()
646{
647  char errmsg[ERRMSGSIZ];
648 
649   
650  switch (PowerS[0].s)
651  {
652     case ISS_ON:
653      if (v4l_base->connectCam(PortT[0].text, errmsg) < 0)
654      {
655          PowerSP.s = IPS_IDLE;
656          PowerS[0].s = ISS_OFF;
657          PowerS[1].s = ISS_ON;
658          IDSetSwitch(&PowerSP, "Error: unable to open device");
659          IDLog("Error: %s\n", errmsg);
660          return;
661      }
662     
663      /* Sucess! */
664      PowerS[0].s = ISS_ON;
665      PowerS[1].s = ISS_OFF;
666      PowerSP.s = IPS_OK;
667      IDSetSwitch(&PowerSP, "Video4Linux Generic Device is online. Retrieving basic data.");
668
669      v4l_base->registerCallback(newFrame, this);
670     
671      IDLog("V4L Device is online. Retrieving basic data.\n");
672      getBasicData();
673     
674      break;
675     
676    case ISS_OFF:
677      PowerS[0].s = ISS_OFF;
678      PowerS[1].s = ISS_ON;
679      PowerSP.s = IPS_IDLE;
680     
681      v4l_base->disconnectCam();
682     
683      IDSetSwitch(&PowerSP, "Video4Linux Generic Device is offline.");
684     
685      break;
686     }
687}
688
689/* Retrieves basic data from the device upon connection.*/
690void V4L_Driver::getBasicData()
691{
692
693  int xmax, ymax, xmin, ymin;
694 
695  v4l_base->getMaxMinSize(xmax, ymax, xmin, ymin);
696
697  /* Width */
698  FrameN[2].value = v4l_base->getWidth();
699  FrameN[2].min = xmin;
700  FrameN[2].max = xmax;
701  V4LFrame->width = (int) FrameN[2].value;
702 
703  /* Height */
704  FrameN[3].value = v4l_base->getHeight();
705  FrameN[3].min = ymin;
706  FrameN[3].max = ymax;
707  V4LFrame->height = (int) FrameN[3].value;
708 
709  IUUpdateMinMax(&FrameNP);
710  IDSetNumber(&FrameNP, NULL);
711 
712  IUSaveText(&camNameT[0], v4l_base->getDeviceName());
713  IDSetText(&camNameTP, NULL);
714
715   #ifndef HAVE_LINUX_VIDEODEV2_H
716     updateV4L1Controls();
717   #else
718    updateV4L2Controls();
719   #endif
720   
721}
722
723#ifdef HAVE_LINUX_VIDEODEV2_H
724void V4L_Driver::updateV4L2Controls()
725{
726    // #1 Query for INTEGER controls, and fill up the structure
727      free(ImageAdjustNP.np);
728      ImageAdjustNP.nnp = 0;
729     
730   if (v4l_base->queryINTControls(&ImageAdjustNP) > 0)
731      IDDefNumber(&ImageAdjustNP, NULL);
732}
733#else
734void V4L_Driver::updateV4L1Controls()
735{
736
737  if ( (v4l_base->getContrast() / divider) > ImageAdjustN[0].max)
738      divider *=2;
739
740  if ( (v4l_base->getHue() / divider) > ImageAdjustN[2].max)
741      divider *=2;
742
743  ImageAdjustN[0].value = v4l_base->getContrast() / divider;
744  ImageAdjustN[1].value = v4l_base->getBrightness() / divider;
745  ImageAdjustN[2].value = v4l_base->getHue() / divider;
746  ImageAdjustN[3].value = v4l_base->getColor() / divider;
747  ImageAdjustN[4].value = v4l_base->getWhiteness() / divider;
748
749  ImageAdjustNP.s = IPS_OK;
750  IDSetNumber(&ImageAdjustNP, NULL);
751 
752}
753#endif
754
755int V4L_Driver::checkPowerS(ISwitchVectorProperty *sp)
756{
757  if (PowerSP.s != IPS_OK)
758  {
759    if (!strcmp(sp->label, ""))
760        IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->name);
761    else
762        IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->label);
763   
764    sp->s = IPS_IDLE;
765    IDSetSwitch(sp, NULL);
766    return -1;
767  }
768
769  return 0;
770}
771
772int V4L_Driver::checkPowerN(INumberVectorProperty *np)
773{
774   
775  if (PowerSP.s != IPS_OK)
776  {
777    if (!strcmp(np->label, ""))
778        IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->name);
779    else
780        IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->label);
781       
782    np->s = IPS_IDLE;
783    IDSetNumber(np, NULL);
784    return -1;
785  }
786
787  return 0;
788}
789
790int V4L_Driver::checkPowerT(ITextVectorProperty *tp)
791{
792
793  if (PowerSP.s != IPS_OK)
794  {
795    if (!strcmp(tp->label, ""))
796        IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->name);
797    else
798        IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->label);
799       
800    tp->s = IPS_IDLE;
801    IDSetText(tp, NULL);
802    return -1;
803  }
804
805  return 0;
806
807}
808
809void V4L_Driver::allocateBuffers()
810{
811     V4LFrame = (img_t *) malloc (sizeof(img_t));
812 
813     if (V4LFrame == NULL)
814     {
815       IDMessage(NULL, "Error: unable to initialize driver. Low memory.");
816       IDLog("Error: unable to initialize driver. Low memory.");
817       exit(-1);
818     }
819
820     fitsData                   = (unsigned char *) malloc (sizeof(unsigned char) * 1);
821     V4LFrame->Y                = (unsigned char *) malloc (sizeof(unsigned char) * 1);
822     V4LFrame->U                = (unsigned char *) malloc (sizeof(unsigned char) * 1);
823     V4LFrame->V                = (unsigned char *) malloc (sizeof(unsigned char) * 1);
824     V4LFrame->colorBuffer      = (unsigned char *) malloc (sizeof(unsigned char) * 1);
825     V4LFrame->compressedFrame  = (unsigned char *) malloc (sizeof(unsigned char) * 1);
826}
827
828void V4L_Driver::releaseBuffers()
829{
830  free(fitsData);
831  free(V4LFrame->Y);
832  free(V4LFrame->U);
833  free(V4LFrame->V);
834  free(V4LFrame->colorBuffer);
835  free(V4LFrame->compressedFrame);
836  free (V4LFrame);
837}
838
839
Note: See TracBrowser for help on using the repository browser.