source: BAORadio/libindi/v1/drivers/video/v4ldriver.cpp@ 689

Last change on this file since 689 was 490, checked in by campagne, 15 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.s = 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].s = ISS_OFF;
379 StreamS[1].s = 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.