1 /*
2  *  cam_ioptron.cpp
3  *  Open PHD Guiding
4  *
5  *  Created by Andy Galasso
6  *  Copyright (c) 2019 Andy Galasso.
7  *  All rights reserved.
8  *
9  *  This source code is distributed under the following "BSD" license
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions are met:
12  *    Redistributions of source code must retain the above copyright notice,
13  *     this list of conditions and the following disclaimer.
14  *    Redistributions in binary form must reproduce the above copyright notice,
15  *     this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *    Neither the name of openphdguiding.org nor the names of its
18  *     contributors may be used to endorse or promote products derived from
19  *     this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  *  POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 #include "phd.h"
36 
37 #if defined(IOPTRON_CAMERA)
38 
39 #include "cam_ioptron.h"
40 #include "cam_wdm_base.h"
41 #include "CVPlatform.h"
42 
43 class IoptronCamera : public CameraWDM
44 {
45 public:
IoptronCamera()46     IoptronCamera()
47     {
48         m_rawYUY2 = true;
49     }
CanSelectCamera() const50     bool CanSelectCamera() const override
51     {
52         // TODO: we could probably hanlde multiple cameras, but would need 2 cameras to test
53         return false;
54     }
GetDevicePixelSize(double * devPixelSize)55     bool GetDevicePixelSize(double *devPixelSize) override
56     {
57         *devPixelSize = 3.75;
58         return false;
59     }
60 
61 protected:
62     bool SelectDeviceAndMode(SelectionContext ctx) override;
63 };
64 
65 struct AutoVidCap
66 {
67     CVVidCapture *m_vc = new CVVidCaptureDSWin32();
68     bool inited = false;
69     bool connected = false;
InitAutoVidCap70     bool Init()
71     {
72         if (CVFAILED(m_vc->Init()))
73             return false;
74         inited = true;
75         return true;
76     }
ConnectAutoVidCap77     bool Connect(int devnr)
78     {
79         if (CVFAILED(m_vc->Connect(devnr)))
80             return false;
81         connected = true;
82         return true;
83     }
getAutoVidCap84     CVVidCapture *get() const { return m_vc; }
~AutoVidCapAutoVidCap85     ~AutoVidCap()
86     {
87         if (connected)
88             m_vc->Disconnect();
89         if (inited)
90             m_vc->Uninit();
91         CVPlatform::GetPlatform()->Release(m_vc);
92     }
93 };
94 
SelectDeviceAndMode(SelectionContext ctx)95 bool IoptronCamera::SelectDeviceAndMode(SelectionContext ctx)
96 {
97     assert(ctx == CTX_CONNECT); // no camera selection for now
98     if (ctx != CTX_CONNECT)
99         return true;
100 
101     AutoVidCap vc;
102 
103     if (!vc.Init())
104     {
105         wxMessageBox(_T("Error initializing WDM services"), _("Error"), wxOK | wxICON_ERROR);
106         return true;
107     }
108 
109     int nr_devs;
110     if (CVFAILED(vc.get()->GetNumDevices(nr_devs)))
111     {
112         wxMessageBox(_T("Error detecting WDM devices"), _("Error"), wxOK | wxICON_ERROR);
113         return true;
114     }
115 
116     Debug.Write(wxString::Format("IOPTRON: %d vidcap devices\n", nr_devs));
117     if (nr_devs == 0)
118         return true;
119 
120     m_deviceNumber = -1;
121 
122     for (int i = 0; i < nr_devs; i++)
123     {
124         CVVidCapture::VIDCAP_DEVICE dev;
125         if (!CVSUCCESS(vc.get()->GetDeviceInfo(i, dev)))
126         {
127             Debug.Write(wxString::Format("IOPTRON: GetDevice failed for VidCap device %d, skipping it\n", i));
128             continue;
129         }
130         if (strcmp(dev.DeviceString, "iOptron iGuider") == 0)
131         {
132             Debug.Write(wxString::Format("IOPTRON: found iGuider at index %d\n", i));
133             if (m_deviceNumber == -1)
134                 m_deviceNumber = i;
135         }
136     }
137     if (m_deviceNumber == -1)
138     {
139         Debug.Write("IOPTRON: iGuider not found\n");
140         return true;
141     }
142     Debug.Write(wxString::Format("IOPTRON: using iGuider at index %d\n", m_deviceNumber));
143 
144     // Connect to camera
145     if (!vc.Connect(m_deviceNumber))
146     {
147         wxMessageBox(wxString::Format("Error connecting to iOptron iGuider"), _("Error"), wxOK | wxICON_ERROR);
148         return true;
149     }
150 
151     int nr_modes = 0;
152     vc.get()->GetNumSupportedModes(nr_modes);
153 
154     m_deviceMode = -1;
155     for (int i = 0; i < nr_modes; i++)
156     {
157         CVVidCapture::VIDCAP_MODE modeInfo;
158         if (CVSUCCESS(vc.get()->GetModeInfo(i, modeInfo)))
159         {
160             if (modeInfo.XRes == 640 && modeInfo.YRes == 960 &&
161                 modeInfo.InputFormat == VIDCAP_FORMAT_YUY2)
162             {
163                 if (m_deviceMode == -1)
164                     m_deviceMode = i;
165             }
166             Debug.Write(wxString::Format("IOPTRON: mode %d: %dx%d (%s) %d fps %s\n", i, modeInfo.XRes,
167                 modeInfo.YRes, vc.get()->GetFormatModeName(modeInfo.InputFormat),
168                 modeInfo.EstFrameRate, i == m_deviceMode ? "<<<<" : ""));
169         }
170         else
171             Debug.Write(wxString::Format("IOPTRON: mode %d: GetModeInfo failed, skipped\n", i));
172     }
173 
174     if (m_deviceMode == -1)
175     {
176         Debug.Write("IOPTRON: iGuider required mode YUY2 640x960 not found\n");
177         return true;
178     }
179 
180     return false;
181 }
182 
MakeIoptronCamera()183 GuideCamera *IoptronCameraFactory::MakeIoptronCamera()
184 {
185     return new IoptronCamera();
186 }
187 
188 #endif // IOPTRON_CAMERA
189