00001 #if 0
00002 V4L INDI Driver
00003 INDI Interface for V4L devices
00004 Copyright (C) 2003-2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
00005
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014 Lesser General Public License for more details.
00015
00016 You should have received a copy of the GNU Lesser General Public
00017 License along with this library; if not, write to the Free Software
00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019
00020 #endif
00021
00022 #include "v4ldriver.h"
00023
00024 V4L_Driver::V4L_Driver()
00025 {
00026 V4LFrame = (img_t *) malloc (sizeof(img_t));
00027
00028 if (V4LFrame == NULL)
00029 {
00030 IDMessage(NULL, "Error: unable to initialize driver. Low memory.");
00031 IDLog("Error: unable to initialize driver. Low memory.");
00032 return;
00033 }
00034
00035 camNameT[0].text = NULL;
00036 PortT[0].text = NULL;
00037 IUSaveText(&PortT[0], "/dev/video0");
00038
00039 divider = 128.;
00040
00041
00042 }
00043
00044 V4L_Driver::~V4L_Driver()
00045 {
00046 free (V4LFrame);
00047 }
00048
00049
00050 void V4L_Driver::initProperties(const char *dev)
00051 {
00052
00053 strncpy(device_name, dev, MAXINDIDEVICE);
00054
00055
00056 fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
00057 fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
00058 fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), dev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
00059
00060
00061 fillText(&PortT[0], "PORT", "Port", "/dev/ttyS0");
00062 fillTextVector(&PortTP, PortT, NARRAY(PortT), dev, "DEVICE_PORT", "Ports", COMM_GROUP, IP_RW, 0, IPS_IDLE);
00063
00064
00065 fillSwitch(&StreamS[0], "ON", "", ISS_OFF);
00066 fillSwitch(&StreamS[1], "OFF", "", ISS_ON);
00067 fillSwitchVector(&StreamSP, StreamS, NARRAY(StreamS), dev, "VIDEO_STREAM", "Video Stream", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
00068
00069
00070 fillSwitch(&CompressS[0], "ON", "", ISS_ON);
00071 fillSwitch(&CompressS[1], "OFF", "", ISS_OFF);
00072 fillSwitchVector(&CompressSP, CompressS, NARRAY(StreamS), dev, "Compression", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
00073
00074
00075 fillSwitch(&ImageTypeS[0], "Grey", "", ISS_ON);
00076 fillSwitch(&ImageTypeS[1], "Color", "", ISS_OFF);
00077 fillSwitchVector(&ImageTypeSP, ImageTypeS, NARRAY(ImageTypeS), dev, "Image Type", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
00078
00079
00080 fillText(&camNameT[0], "Model", "", "");
00081 fillTextVector(&camNameTP, camNameT, NARRAY(camNameT), dev, "Camera Model", "", COMM_GROUP, IP_RO, 0, IPS_IDLE);
00082
00083
00084 fillNumber(&ExposeTimeN[0], "EXPOSE_DURATION", "Duration (s)", "%5.2f", 0., 36000., 0.5, 1.);
00085 fillNumberVector(&ExposeTimeNP, ExposeTimeN, NARRAY(ExposeTimeN), dev, "CCD_EXPOSE_DURATION", "Expose", COMM_GROUP, IP_RW, 60, IPS_IDLE);
00086
00087
00088 fillNumber(&FrameRateN[0], "RATE", "Rate", "%0.f", 1., 50., 1., 10.);
00089 fillNumberVector(&FrameRateNP, FrameRateN, NARRAY(FrameRateN), dev, "FRAME_RATE", "Frame Rate", COMM_GROUP, IP_RW, 60, IPS_IDLE);
00090
00091
00092 fillNumber(&FrameN[0], "X", "X", "%.0f", 0., 0., 0., 0.);
00093 fillNumber(&FrameN[1], "Y", "Y", "%.0f", 0., 0., 0., 0.);
00094 fillNumber(&FrameN[2], "WIDTH", "Width", "%.0f", 0., 0., 10., 0.);
00095 fillNumber(&FrameN[3], "HEIGHT", "Height", "%.0f", 0., 0., 10., 0.);
00096 fillNumberVector(&FrameNP, FrameN, NARRAY(FrameN), dev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
00097
00098
00099
00100
00101
00102 #ifndef HAVE_LINUX_VIDEODEV2_H
00103 fillNumber(&ImageAdjustN[0], "Contrast", "", "%0.f", 0., 256., 1., 0.);
00104 fillNumber(&ImageAdjustN[1], "Brightness", "", "%0.f", 0., 256., 1., 0.);
00105 fillNumber(&ImageAdjustN[2], "Hue", "", "%0.f", 0., 256., 1., 0.);
00106 fillNumber(&ImageAdjustN[3], "Color", "", "%0.f", 0., 256., 1., 0.);
00107 fillNumber(&ImageAdjustN[4], "Whiteness", "", "%0.f", 0., 256., 1., 0.);
00108 fillNumberVector(&ImageAdjustNP, ImageAdjustN, NARRAY(ImageAdjustN), dev, "Image Adjustments", "", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
00109 #else
00110 fillNumberVector(&ImageAdjustNP, NULL, 0, dev, "Image Adjustments", "", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
00111 #endif
00112
00113
00114 strcpy(imageB.name, "CCD1");
00115 strcpy(imageB.label, "Feed");
00116 strcpy(imageB.format, "");
00117 imageB.blob = 0;
00118 imageB.bloblen = 0;
00119 imageB.size = 0;
00120 imageB.bvp = 0;
00121 imageB.aux0 = 0;
00122 imageB.aux1 = 0;
00123 imageB.aux2 = 0;
00124
00125 strcpy(imageBP.device, dev);
00126 strcpy(imageBP.name, "Video");
00127 strcpy(imageBP.label, "Video");
00128 strcpy(imageBP.group, COMM_GROUP);
00129 strcpy(imageBP.timestamp, "");
00130 imageBP.p = IP_RO;
00131 imageBP.timeout = 0;
00132 imageBP.s = IPS_IDLE;
00133 imageBP.bp = &imageB;
00134 imageBP.nbp = 1;
00135 imageBP.aux = 0;
00136
00137 }
00138
00139 void V4L_Driver::initCamBase()
00140 {
00141 #ifndef HAVE_LINUX_VIDEODEV2_H
00142 v4l_base = new V4L1_Base();
00143 #else
00144 v4l_base = new V4L2_Base();
00145 #endif
00146 }
00147
00148 void V4L_Driver::ISGetProperties (const char *dev)
00149 {
00150
00151 if (dev && strcmp (device_name, dev))
00152 return;
00153
00154
00155 IDDefSwitch(&PowerSP, NULL);
00156 IDDefText(&PortTP, NULL);
00157 IDDefText(&camNameTP, NULL);
00158 IDDefSwitch(&StreamSP, NULL);
00159 #ifndef HAVE_LINUX_VIDEODEV2_H
00160 IDDefNumber(&FrameRateNP, NULL);
00161 #endif
00162 IDDefNumber(&ExposeTimeNP, NULL);
00163 IDDefBLOB(&imageBP, NULL);
00164
00165
00166 IDDefSwitch(&CompressSP, NULL);
00167 IDDefSwitch(&ImageTypeSP, NULL);
00168 IDDefNumber(&FrameNP, NULL);
00169
00170 #ifndef HAVE_LINUX_VIDEODEV2_H
00171 IDDefNumber(&ImageAdjustNP, NULL);
00172 #endif
00173
00174
00175
00176 }
00177
00178 void V4L_Driver::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
00179 {
00180 char errmsg[ERRMSGSIZ];
00181
00182
00183 if (dev && strcmp (device_name, dev))
00184 return;
00185
00186
00187 if (!strcmp (name, PowerSP.name))
00188 {
00189 IUResetSwitches(&PowerSP);
00190 IUUpdateSwitches(&PowerSP, states, names, n);
00191 connectCamera();
00192 return;
00193 }
00194
00195
00196 if (!strcmp(name, CompressSP.name))
00197 {
00198 IUResetSwitches(&CompressSP);
00199 IUUpdateSwitches(&CompressSP, states, names, n);
00200 CompressSP.s = IPS_OK;
00201
00202 IDSetSwitch(&CompressSP, NULL);
00203 return;
00204 }
00205
00206
00207 if (!strcmp(name, ImageTypeSP.name))
00208 {
00209 IUResetSwitches(&ImageTypeSP);
00210 IUUpdateSwitches(&ImageTypeSP, states, names, n);
00211 ImageTypeSP.s = IPS_OK;
00212
00213 IDSetSwitch(&ImageTypeSP, NULL);
00214 return;
00215 }
00216
00217
00218 if (!strcmp(name, StreamSP.name))
00219 {
00220
00221 if (checkPowerS(&StreamSP))
00222 return;
00223
00224 IUResetSwitches(&StreamSP);
00225 IUUpdateSwitches(&StreamSP, states, names, n);
00226 StreamSP.s = IPS_IDLE;
00227
00228
00229 if (StreamS[0].s == ISS_ON)
00230 {
00231 frameCount = 0;
00232 IDLog("Starting the video stream.\n");
00233 v4l_base->start_capturing(errmsg);
00234 StreamSP.s = IPS_BUSY;
00235 }
00236 else
00237 {
00238 IDLog("The video stream has been disabled. Frame count %d\n", frameCount);
00239 v4l_base->stop_capturing(errmsg);
00240 }
00241
00242 IDSetSwitch(&StreamSP, NULL);
00243 return;
00244 }
00245
00246 }
00247
00248 void V4L_Driver::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int )
00249 {
00250 IText *tp;
00251
00252
00253
00254 if (dev && strcmp (device_name, dev))
00255 return;
00256
00257 if (!strcmp(name, PortTP.name) )
00258 {
00259 PortTP.s = IPS_OK;
00260 tp = IUFindText( &PortTP, names[0] );
00261 if (!tp)
00262 return;
00263
00264 IUSaveText(tp, texts[0]);
00265 IDSetText (&PortTP, NULL);
00266 return;
00267 }
00268 }
00269
00270 void V4L_Driver::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
00271 {
00272 char errmsg[ERRMSGSIZ];
00273
00274
00275 if (dev && strcmp (device_name, dev))
00276 return;
00277
00278
00279
00280 if (!strcmp (FrameNP.name, name))
00281 {
00282 if (checkPowerN(&FrameNP))
00283 return;
00284
00285 int oldW = (int) FrameN[2].value;
00286 int oldH = (int) FrameN[3].value;
00287
00288 FrameNP.s = IPS_OK;
00289
00290 if (IUUpdateNumbers(&FrameNP, values, names, n) < 0)
00291 return;
00292
00293 if (v4l_base->setSize( (int) FrameN[2].value, (int) FrameN[3].value) != -1)
00294 {
00295 FrameN[2].value = v4l_base->getWidth();
00296 FrameN[3].value = v4l_base->getHeight();
00297 IDSetNumber(&FrameNP, NULL);
00298 return;
00299 }
00300 else
00301 {
00302 FrameN[2].value = oldW;
00303 FrameN[3].value = oldH;
00304 FrameNP.s = IPS_ALERT;
00305 IDSetNumber(&FrameNP, "Failed to set a new image size.");
00306 }
00307
00308 return;
00309 }
00310
00311 #ifndef HAVE_LINUX_VIDEODEV2_H
00312
00313 if (!strcmp (FrameRateNP.name, name))
00314 {
00315 if (checkPowerN(&FrameRateNP))
00316 return;
00317
00318 FrameRateNP.s = IPS_IDLE;
00319
00320 if (IUUpdateNumbers(&FrameRateNP, values, names, n) < 0)
00321 return;
00322
00323 v4l_base->setFPS( (int) FrameRateN[0].value );
00324
00325 FrameRateNP.s = IPS_OK;
00326 IDSetNumber(&FrameRateNP, NULL);
00327 return;
00328 }
00329 #endif
00330
00331
00332 if (!strcmp (ImageAdjustNP.name, name))
00333 {
00334 if (checkPowerN(&ImageAdjustNP))
00335 return;
00336
00337 ImageAdjustNP.s = IPS_IDLE;
00338
00339 if (IUUpdateNumbers(&ImageAdjustNP, values, names, n) < 0)
00340 return;
00341
00342 #ifndef HAVE_LINUX_VIDEODEV2_H
00343 v4l_base->setContrast( (int) (ImageAdjustN[0].value * divider));
00344 v4l_base->setBrightness( (int) (ImageAdjustN[1].value * divider));
00345 v4l_base->setHue( (int) (ImageAdjustN[2].value * divider));
00346 v4l_base->setColor( (int) (ImageAdjustN[3].value * divider));
00347 v4l_base->setWhiteness( (int) (ImageAdjustN[4].value * divider));
00348
00349 ImageAdjustN[0].value = v4l_base->getContrast() / divider;
00350 ImageAdjustN[1].value = v4l_base->getBrightness() / divider;
00351 ImageAdjustN[2].value = v4l_base->getHue() / divider;
00352 ImageAdjustN[3].value = v4l_base->getColor() / divider;
00353 ImageAdjustN[4].value = v4l_base->getWhiteness() / divider;
00354
00355 #else
00356 unsigned int ctrl_id;
00357 for (int i=0; i < ImageAdjustNP.nnp; i++)
00358 {
00359 ctrl_id = *((unsigned int *) ImageAdjustNP.np[i].aux0);
00360 if (v4l_base->setINTControl( ctrl_id , ImageAdjustNP.np[i].value, errmsg) < 0)
00361 {
00362 ImageAdjustNP.s = IPS_ALERT;
00363 IDSetNumber(&ImageAdjustNP, "Unable to adjust setting. %s", errmsg);
00364 return;
00365 }
00366 }
00367 #endif
00368
00369 ImageAdjustNP.s = IPS_OK;
00370 IDSetNumber(&ImageAdjustNP, NULL);
00371 return;
00372 }
00373
00374
00375
00376 if (!strcmp (ExposeTimeNP.name, name))
00377 {
00378
00379 if (checkPowerN(&ExposeTimeNP))
00380 return;
00381
00382 if (StreamS[0].s == ISS_ON)
00383 v4l_base->stop_capturing(errmsg);
00384
00385 StreamS[0].s = ISS_OFF;
00386 StreamS[1].s = ISS_ON;
00387 StreamSP.s = IPS_IDLE;
00388 IDSetSwitch(&StreamSP, NULL);
00389
00390 V4LFrame->expose = 1000;
00391
00392 v4l_base->start_capturing(errmsg);
00393 ExposeTimeNP.s = IPS_BUSY;
00394 IDSetNumber(&ExposeTimeNP, NULL);
00395
00396 return;
00397 }
00398
00399
00400
00401 }
00402
00403 void V4L_Driver::newFrame(void *p)
00404 {
00405 ((V4L_Driver *) (p))->updateFrame();
00406 }
00407
00408 void V4L_Driver::updateFrame()
00409 {
00410 char errmsg[ERRMSGSIZ];
00411 static int dropLarge = 3;
00412
00413 if (StreamSP.s == IPS_BUSY)
00414 {
00415 frameCount++;
00416
00417
00418 if (FrameN[2].value > 160)
00419 {
00420 dropLarge--;
00421 if (dropLarge == 0)
00422 {
00423 dropLarge = 3;
00424 return;
00425 }
00426 else if (dropLarge < 2) return;
00427
00428 }
00429
00430 updateStream();
00431 }
00432 else if (ExposeTimeNP.s == IPS_BUSY)
00433 {
00434 V4LFrame->Y = v4l_base->getY();
00435 v4l_base->stop_capturing(errmsg);
00436 grabImage();
00437 }
00438
00439 }
00440
00441 void V4L_Driver::updateStream()
00442 {
00443
00444 int width = v4l_base->getWidth();
00445 int height = v4l_base->getHeight();
00446 uLongf compressedBytes = 0;
00447 uLong totalBytes;
00448 unsigned char *targetFrame;
00449 int r;
00450
00451 if (PowerS[0].s == ISS_OFF || StreamS[0].s == ISS_OFF) return;
00452
00453 if (ImageTypeS[0].s == ISS_ON)
00454 V4LFrame->Y = v4l_base->getY();
00455 else
00456 V4LFrame->colorBuffer = v4l_base->getColorBuffer();
00457
00458 totalBytes = ImageTypeS[0].s == ISS_ON ? width * height : width * height * 4;
00459 targetFrame = ImageTypeS[0].s == ISS_ON ? V4LFrame->Y : V4LFrame->colorBuffer;
00460
00461
00462 if (CompressS[0].s == ISS_ON)
00463 {
00464
00465 V4LFrame->compressedFrame = (unsigned char *) realloc (V4LFrame->compressedFrame, sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
00466
00467 compressedBytes = sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3;
00468
00469 r = compress2(V4LFrame->compressedFrame, &compressedBytes, targetFrame, totalBytes, 4);
00470 if (r != Z_OK)
00471 {
00472
00473 IDLog("internal error - compression failed: %d\n", r);
00474 return;
00475 }
00476
00477
00478 imageB.blob = V4LFrame->compressedFrame;
00479 imageB.bloblen = compressedBytes;
00480 imageB.size = totalBytes;
00481 strcpy(imageB.format, ".stream.z");
00482 }
00483 else
00484 {
00485
00486 imageB.blob = targetFrame;
00487 imageB.bloblen = totalBytes;
00488 imageB.size = totalBytes;
00489 strcpy(imageB.format, ".stream");
00490 }
00491
00492 imageBP.s = IPS_OK;
00493 IDSetBLOB (&imageBP, NULL);
00494
00495 #ifndef HAVE_LINUX_VIDEODEV2_H
00496 char errmsg[ERRMSGSIZ];
00497 v4l_base->start_capturing(errmsg);
00498 #endif
00499 }
00500
00501
00502
00503
00504 int V4L_Driver::grabImage()
00505 {
00506 int err, fd;
00507 char errmsg[ERRMSG_SIZE];
00508 char filename[] = "/tmp/fitsXXXXXX";
00509
00510
00511 if ((fd = mkstemp(filename)) < 0)
00512 {
00513 IDMessage(device_name, "Error making temporary filename.");
00514 IDLog("Error making temporary filename.\n");
00515 return -1;
00516 }
00517 close(fd);
00518
00519 err = writeFITS(filename, errmsg);
00520 if (err)
00521 {
00522 IDMessage(device_name, errmsg, NULL);
00523 return -1;
00524 }
00525
00526 return 0;
00527 }
00528
00529 int V4L_Driver::writeFITS(const char * filename, char errmsg[])
00530 {
00531 FITS_FILE* ofp;
00532 int i, bpp, bpsl, width, height;
00533 long nbytes;
00534 FITS_HDU_LIST *hdu;
00535
00536 ofp = fits_open (filename, "w");
00537 if (!ofp)
00538 {
00539 snprintf(errmsg, ERRMSG_SIZE, "Error: cannot open file for writing.");
00540 return (-1);
00541 }
00542
00543 width = v4l_base->getWidth();
00544 height = v4l_base->getHeight();
00545 bpp = 1;
00546 bpsl = bpp * width;
00547 nbytes = 0;
00548
00549 hdu = create_fits_header (ofp, width, height, bpp);
00550 if (hdu == NULL)
00551 {
00552 snprintf(errmsg, ERRMSG_SIZE, "Error: creating FITS header failed.");
00553 return (-1);
00554 }
00555 if (fits_write_header (ofp, hdu) < 0)
00556 {
00557 snprintf(errmsg, ERRMSG_SIZE, "Error: writing to FITS header failed.");
00558 return (-1);
00559 }
00560
00561 for (i= height - 1; i >=0 ; i--)
00562 {
00563 fwrite(V4LFrame->Y + (i * width), 1, width, ofp->fp);
00564 nbytes += bpsl;
00565 }
00566
00567 nbytes = nbytes % FITS_RECORD_SIZE;
00568 if (nbytes)
00569 {
00570 while (nbytes++ < FITS_RECORD_SIZE)
00571 putc (0, ofp->fp);
00572 }
00573
00574 if (ferror (ofp->fp))
00575 {
00576 snprintf(errmsg, ERRMSG_SIZE, "Error: write error occured");
00577 return (-1);
00578 }
00579
00580 fits_close (ofp);
00581
00582
00583 ExposeTimeNP.s = IPS_OK;
00584 IDSetNumber(&ExposeTimeNP, NULL);
00585
00586 uploadFile(filename);
00587
00588 return 0;
00589
00590 }
00591
00592 void V4L_Driver::uploadFile(const char * filename)
00593 {
00594
00595 FILE * fitsFile;
00596 unsigned char *fitsData;
00597 int r=0;
00598 unsigned int nr = 0;
00599 uLong totalBytes;
00600 uLongf compressedBytes = 0;
00601 struct stat stat_p;
00602
00603 if ( -1 == stat (filename, &stat_p))
00604 {
00605 IDLog(" Error occoured attempting to stat %s\n", filename);
00606 return;
00607 }
00608
00609 totalBytes = stat_p.st_size;
00610 fitsData = new unsigned char[totalBytes];
00611
00612 fitsFile = fopen(filename, "r");
00613
00614 if (fitsFile == NULL)
00615 return;
00616
00617
00618 for (unsigned int i=0; i < totalBytes; i+= nr)
00619 {
00620 nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
00621
00622 if (nr <= 0)
00623 {
00624 IDLog("Error reading temporary FITS file.\n");
00625 return;
00626 }
00627 }
00628
00629 if (CompressS[0].s == ISS_ON)
00630 {
00631
00632 V4LFrame->compressedFrame = (unsigned char *) realloc (V4LFrame->compressedFrame, sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
00633
00634 compressedBytes = sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3;
00635
00636
00637 r = compress2(V4LFrame->compressedFrame, &compressedBytes, fitsData, totalBytes, 9);
00638 if (r != Z_OK)
00639 {
00640
00641 IDLog("internal error - compression failed: %d\n", r);
00642 return;
00643 }
00644
00645
00646 imageB.blob = V4LFrame->compressedFrame;
00647 imageB.bloblen = compressedBytes;
00648 imageB.size = totalBytes;
00649 strcpy(imageB.format, ".fits.z");
00650 }
00651 else
00652 {
00653 imageB.blob = fitsData;
00654 imageB.bloblen = totalBytes;
00655 imageB.size = totalBytes;
00656 strcpy(imageB.format, ".fits");
00657 }
00658
00659 imageBP.s = IPS_OK;
00660 IDSetBLOB (&imageBP, NULL);
00661
00662 delete (fitsData);
00663 }
00664
00665 void V4L_Driver::connectCamera()
00666 {
00667 char errmsg[ERRMSGSIZ];
00668
00669
00670 switch (PowerS[0].s)
00671 {
00672 case ISS_ON:
00673 if (v4l_base->connectCam(PortT[0].text, errmsg) < 0)
00674 {
00675 PowerSP.s = IPS_IDLE;
00676 PowerS[0].s = ISS_OFF;
00677 PowerS[1].s = ISS_ON;
00678 IDSetSwitch(&PowerSP, "Error: unable to open device");
00679 IDLog("Error: %s\n", errmsg);
00680 return;
00681 }
00682
00683
00684 PowerS[0].s = ISS_ON;
00685 PowerS[1].s = ISS_OFF;
00686 PowerSP.s = IPS_OK;
00687 IDSetSwitch(&PowerSP, "Video4Linux Generic Device is online. Retrieving basic data.");
00688
00689 v4l_base->registerCallback(newFrame, this);
00690
00691 V4LFrame->compressedFrame = (unsigned char *) malloc (sizeof(unsigned char) * 1);
00692
00693 IDLog("V4L Device is online. Retrieving basic data.\n");
00694 getBasicData();
00695
00696 break;
00697
00698 case ISS_OFF:
00699 PowerS[0].s = ISS_OFF;
00700 PowerS[1].s = ISS_ON;
00701 PowerSP.s = IPS_IDLE;
00702
00703 free(V4LFrame->compressedFrame);
00704 V4LFrame->compressedFrame = NULL;
00705 v4l_base->disconnectCam();
00706
00707 IDSetSwitch(&PowerSP, "Video4Linux Generic Device is offline.");
00708
00709 break;
00710 }
00711 }
00712
00713
00714 void V4L_Driver::getBasicData()
00715 {
00716
00717 int xmax, ymax, xmin, ymin;
00718
00719 v4l_base->getMaxMinSize(xmax, ymax, xmin, ymin);
00720
00721
00722 FrameN[2].value = v4l_base->getWidth();
00723 FrameN[2].min = xmin;
00724 FrameN[2].max = xmax;
00725
00726
00727 FrameN[3].value = v4l_base->getHeight();
00728 FrameN[3].min = ymin;
00729 FrameN[3].max = ymax;
00730
00731 IUUpdateMinMax(&FrameNP);
00732 IDSetNumber(&FrameNP, NULL);
00733
00734 IUSaveText(&camNameT[0], v4l_base->getDeviceName());
00735 IDSetText(&camNameTP, NULL);
00736
00737 #ifndef HAVE_LINUX_VIDEODEV2_H
00738 updateV4L1Controls();
00739 #else
00740 updateV4L2Controls();
00741 #endif
00742
00743 }
00744
00745 #ifdef HAVE_LINUX_VIDEODEV2_H
00746 void V4L_Driver::updateV4L2Controls()
00747 {
00748
00749 free(ImageAdjustNP.np);
00750 ImageAdjustNP.nnp = 0;
00751
00752 if (v4l_base->queryINTControls(&ImageAdjustNP) > 0)
00753 IDDefNumber(&ImageAdjustNP, NULL);
00754 }
00755 #else
00756 void V4L_Driver::updateV4L1Controls()
00757 {
00758
00759 if ( (v4l_base->getContrast() / divider) > ImageAdjustN[0].max)
00760 divider *=2;
00761
00762 if ( (v4l_base->getHue() / divider) > ImageAdjustN[2].max)
00763 divider *=2;
00764
00765 ImageAdjustN[0].value = v4l_base->getContrast() / divider;
00766 ImageAdjustN[1].value = v4l_base->getBrightness() / divider;
00767 ImageAdjustN[2].value = v4l_base->getHue() / divider;
00768 ImageAdjustN[3].value = v4l_base->getColor() / divider;
00769 ImageAdjustN[4].value = v4l_base->getWhiteness() / divider;
00770
00771 ImageAdjustNP.s = IPS_OK;
00772 IDSetNumber(&ImageAdjustNP, NULL);
00773
00774 }
00775 #endif
00776
00777 int V4L_Driver::checkPowerS(ISwitchVectorProperty *sp)
00778 {
00779 if (PowerSP.s != IPS_OK)
00780 {
00781 if (!strcmp(sp->label, ""))
00782 IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->name);
00783 else
00784 IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->label);
00785
00786 sp->s = IPS_IDLE;
00787 IDSetSwitch(sp, NULL);
00788 return -1;
00789 }
00790
00791 return 0;
00792 }
00793
00794 int V4L_Driver::checkPowerN(INumberVectorProperty *np)
00795 {
00796
00797 if (PowerSP.s != IPS_OK)
00798 {
00799 if (!strcmp(np->label, ""))
00800 IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->name);
00801 else
00802 IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->label);
00803
00804 np->s = IPS_IDLE;
00805 IDSetNumber(np, NULL);
00806 return -1;
00807 }
00808
00809 return 0;
00810 }
00811
00812 int V4L_Driver::checkPowerT(ITextVectorProperty *tp)
00813 {
00814
00815 if (PowerSP.s != IPS_OK)
00816 {
00817 if (!strcmp(tp->label, ""))
00818 IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->name);
00819 else
00820 IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->label);
00821
00822 tp->s = IPS_IDLE;
00823 IDSetText(tp, NULL);
00824 return -1;
00825 }
00826
00827 return 0;
00828
00829 }
00830
00831 FITS_HDU_LIST * V4L_Driver::create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp)
00832 {
00833
00834 FITS_HDU_LIST *hdulist;
00835 char expose_s[80];
00836 char obsDate[80];
00837 char instrumentName[80];
00838 char ts[32];
00839
00840 struct tm *tp;
00841 time_t t;
00842 time (&t);
00843 tp = gmtime (&t);
00844 strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
00845
00846 snprintf(instrumentName, 80, "INSTRUME= '%s'", v4l_base->getDeviceName());
00847 snprintf(obsDate, 80, "DATE-OBS= '%s' /Observation Date UTC", ts);
00848
00849 hdulist = fits_add_hdu (ofp);
00850 if (hdulist == NULL) return (NULL);
00851
00852 hdulist->used.simple = 1;
00853 hdulist->bitpix = 8;
00854 hdulist->naxis = 2;
00855 hdulist->naxisn[0] = width;
00856 hdulist->naxisn[1] = height;
00857 hdulist->naxisn[2] = bpp;
00858 hdulist->used.datamin = 0;
00859 hdulist->used.datamax = 0;
00860 hdulist->used.bzero = 1;
00861 hdulist->bzero = 0.0;
00862 hdulist->used.bscale = 1;
00863 hdulist->bscale = 1.0;
00864
00865 snprintf(expose_s, sizeof(expose_s), "EXPOSURE= %d / milliseconds", V4LFrame->expose);
00866
00867 fits_add_card (hdulist, expose_s);
00868 fits_add_card (hdulist, instrumentName);
00869 fits_add_card (hdulist, obsDate);
00870
00871 return (hdulist);
00872 }
00873
00874
00875