1 /* Webcamoid, webcam capture application.
2  * Copyright (C) 2018  Gonzalo Exequiel Pedone
3  *
4  * Webcamoid is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Webcamoid is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Webcamoid. If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Web-Site: http://webcamoid.github.io/
18  */
19 
20 #include <map>
21 #include <vector>
22 #include <dshow.h>
23 
24 #include "videoprocamp.h"
25 #include "PlatformUtils/src/utils.h"
26 #include "VCamUtils/src/utils.h"
27 
28 #define AK_CUR_INTERFACE "VideoProcAmp"
29 
30 namespace AkVCam
31 {
32     class VideoProcAmpPrivate
33     {
34         public:
35             std::map<LONG, LONG> m_control;
36     };
37 
38     class ProcAmpPrivate
39     {
40         public:
41             LONG property;
42             LONG min;
43             LONG max;
44             LONG step;
45             LONG defaultValue;
46             LONG flags;
47 
controls()48             inline static const std::vector<ProcAmpPrivate> &controls()
49             {
50                 static const std::vector<ProcAmpPrivate> controls {
51                     {VideoProcAmp_Brightness , -255, 255, 1, 0, CameraControl_Flags_Manual},
52                     {VideoProcAmp_Contrast   , -255, 255, 1, 0, CameraControl_Flags_Manual},
53                     {VideoProcAmp_Saturation , -255, 255, 1, 0, CameraControl_Flags_Manual},
54                     {VideoProcAmp_Gamma      , -255, 255, 1, 0, CameraControl_Flags_Manual},
55                     {VideoProcAmp_Hue        , -359, 359, 1, 0, CameraControl_Flags_Manual},
56                     {VideoProcAmp_ColorEnable,    0,   1, 1, 1, CameraControl_Flags_Manual}
57                 };
58 
59                 return controls;
60             }
61 
byProperty(LONG property)62             static inline const ProcAmpPrivate *byProperty(LONG property)
63             {
64                 for (auto &control: controls())
65                     if (control.property == property)
66                         return &control;
67 
68                 return nullptr;
69             }
70     };
71 }
72 
VideoProcAmp()73 AkVCam::VideoProcAmp::VideoProcAmp():
74     CUnknown(this, IID_IAMVideoProcAmp)
75 {
76     this->d = new VideoProcAmpPrivate;
77 }
78 
~VideoProcAmp()79 AkVCam::VideoProcAmp::~VideoProcAmp()
80 {
81     delete this->d;
82 }
83 
GetRange(LONG Property,LONG * pMin,LONG * pMax,LONG * pSteppingDelta,LONG * pDefault,LONG * pCapsFlags)84 HRESULT AkVCam::VideoProcAmp::GetRange(LONG Property,
85                                        LONG *pMin,
86                                        LONG *pMax,
87                                        LONG *pSteppingDelta,
88                                        LONG *pDefault,
89                                        LONG *pCapsFlags)
90 {
91     AkLogMethod();
92 
93     if (!pMin || !pMax || !pSteppingDelta || !pDefault || !pCapsFlags)
94         return E_POINTER;
95 
96     *pMin = 0;
97     *pMax = 0;
98     *pSteppingDelta = 0;
99     *pDefault = 0;
100     *pCapsFlags = 0;
101 
102     for (auto &control: ProcAmpPrivate::controls())
103         if (control.property == Property) {
104             *pMin = control.min;
105             *pMax = control.max;
106             *pSteppingDelta = control.step;
107             *pDefault = control.defaultValue;
108             *pCapsFlags = control.flags;
109 
110             return S_OK;
111         }
112 
113     return E_PROP_ID_UNSUPPORTED;
114 }
115 
Set(LONG Property,LONG lValue,LONG Flags)116 HRESULT AkVCam::VideoProcAmp::Set(LONG Property, LONG lValue, LONG Flags)
117 {
118     AkLogMethod();
119 
120     for (auto &control: ProcAmpPrivate::controls())
121         if (control.property == Property) {
122             if (lValue < control.min
123                 || lValue > control.max
124                 || Flags != control.flags)
125                 return E_INVALIDARG;
126 
127             this->d->m_control[Property] = lValue;
128             AKVCAM_EMIT(this, PropertyChanged, Property, lValue, Flags)
129 
130             return S_OK;
131         }
132 
133     return E_PROP_ID_UNSUPPORTED;
134 }
135 
Get(LONG Property,LONG * lValue,LONG * Flags)136 HRESULT AkVCam::VideoProcAmp::Get(LONG Property, LONG *lValue, LONG *Flags)
137 {
138     AkLogMethod();
139 
140     if (!lValue || !Flags)
141         return E_POINTER;
142 
143     *lValue = 0;
144     *Flags = 0;
145 
146     for (auto &control: ProcAmpPrivate::controls())
147         if (control.property == Property) {
148             if (this->d->m_control.count(Property))
149                 *lValue = this->d->m_control[Property];
150             else
151                 *lValue = control.defaultValue;
152 
153             *Flags = control.flags;
154 
155             return S_OK;
156         }
157 
158     return E_PROP_ID_UNSUPPORTED;
159 }
160