VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp

Last change on this file was 98293, checked in by vboxsync, 16 months ago

Main/src-server: hr -> hrc. bugref:10223

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: HostVideoInputDeviceImpl.cpp 98293 2023-01-25 01:22:39Z vboxsync $ */
2/** @file
3 * Host video capture device implementation.
4 */
5
6/*
7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_HOSTVIDEOINPUTDEVICE
29#include "HostVideoInputDeviceImpl.h"
30#include "LoggingNew.h"
31#include "VirtualBoxImpl.h"
32#ifdef VBOX_WITH_EXTPACK
33# include "ExtPackManagerImpl.h"
34#endif
35
36#include <iprt/err.h>
37#include <iprt/ldr.h>
38#include <iprt/path.h>
39
40#include <VBox/sup.h>
41
42/*
43 * HostVideoInputDevice implementation.
44 */
45DEFINE_EMPTY_CTOR_DTOR(HostVideoInputDevice)
46
47HRESULT HostVideoInputDevice::FinalConstruct()
48{
49 return BaseFinalConstruct();
50}
51
52void HostVideoInputDevice::FinalRelease()
53{
54 uninit();
55
56 BaseFinalRelease();
57}
58
59/*
60 * Initializes the instance.
61 */
62HRESULT HostVideoInputDevice::init(const com::Utf8Str &name, const com::Utf8Str &path, const com::Utf8Str &alias)
63{
64 LogFlowThisFunc(("\n"));
65
66 /* Enclose the state transition NotReady->InInit->Ready */
67 AutoInitSpan autoInitSpan(this);
68 AssertReturn(autoInitSpan.isOk(), E_FAIL);
69
70 m.name = name;
71 m.path = path;
72 m.alias = alias;
73
74 /* Confirm a successful initialization */
75 autoInitSpan.setSucceeded();
76
77 return S_OK;
78}
79
80/*
81 * Uninitializes the instance.
82 * Called either from FinalRelease() or by the parent when it gets destroyed.
83 */
84void HostVideoInputDevice::uninit()
85{
86 LogFlowThisFunc(("\n"));
87
88 /* Enclose the state transition Ready->InUninit->NotReady */
89 AutoUninitSpan autoUninitSpan(this);
90 if (autoUninitSpan.uninitDone())
91 return;
92
93 m.name.setNull();
94 m.path.setNull();
95 m.alias.setNull();
96}
97
98static HRESULT hostVideoInputDeviceAdd(HostVideoInputDeviceList *pList,
99 const com::Utf8Str &name,
100 const com::Utf8Str &path,
101 const com::Utf8Str &alias)
102{
103 ComObjPtr<HostVideoInputDevice> obj;
104 HRESULT hrc = obj.createObject();
105 if (SUCCEEDED(hrc))
106 {
107 hrc = obj->init(name, path, alias);
108 if (SUCCEEDED(hrc))
109 pList->push_back(obj);
110 }
111 return hrc;
112}
113
114static DECLCALLBACK(int) hostWebcamAdd(void *pvUser,
115 const char *pszName,
116 const char *pszPath,
117 const char *pszAlias,
118 uint64_t *pu64Result)
119{
120 HostVideoInputDeviceList *pList = (HostVideoInputDeviceList *)pvUser;
121 HRESULT hrc = hostVideoInputDeviceAdd(pList, pszName, pszPath, pszAlias);
122 if (FAILED(hrc))
123 {
124 *pu64Result = (uint64_t)hrc;
125 return VERR_NOT_SUPPORTED;
126 }
127 return VINF_SUCCESS;
128}
129
130/** @todo These typedefs must be in a header. */
131typedef DECLCALLBACKTYPE(int, FNVBOXHOSTWEBCAMADD,(void *pvUser,
132 const char *pszName,
133 const char *pszPath,
134 const char *pszAlias,
135 uint64_t *pu64Result));
136typedef FNVBOXHOSTWEBCAMADD *PFNVBOXHOSTWEBCAMADD;
137
138typedef DECLCALLBACKTYPE(int, FNVBOXHOSTWEBCAMLIST,(PFNVBOXHOSTWEBCAMADD pfnWebcamAdd,
139 void *pvUser,
140 uint64_t *pu64WebcamAddResult));
141typedef FNVBOXHOSTWEBCAMLIST *PFNVBOXHOSTWEBCAMLIST;
142
143
144/*
145 * Work around clang being unhappy about PFNVBOXHOSTWEBCAMLIST
146 * ("exception specifications are not allowed beyond a single level of
147 * indirection"). The original comment for 13.0 check said: "assuming
148 * this issue will be fixed eventually". Well, 13.0 is now out, and
149 * it was not.
150 */
151#define CLANG_EXCEPTION_SPEC_HACK (RT_CLANG_PREREQ(11, 0) /* && !RT_CLANG_PREREQ(13, 0) */)
152
153#if CLANG_EXCEPTION_SPEC_HACK
154static int loadHostWebcamLibrary(const char *pszPath, RTLDRMOD *phmod, void **ppfn)
155#else
156static int loadHostWebcamLibrary(const char *pszPath, RTLDRMOD *phmod, PFNVBOXHOSTWEBCAMLIST *ppfn)
157#endif
158{
159 int vrc;
160 if (RTPathHavePath(pszPath))
161 {
162 RTLDRMOD hmod = NIL_RTLDRMOD;
163 RTERRINFOSTATIC ErrInfo;
164 vrc = SUPR3HardenedLdrLoadPlugIn(pszPath, &hmod, RTErrInfoInitStatic(&ErrInfo));
165 if (RT_SUCCESS(vrc))
166 {
167 static const char s_szSymbol[] = "VBoxHostWebcamList";
168 vrc = RTLdrGetSymbol(hmod, s_szSymbol, (void **)ppfn);
169 if (RT_SUCCESS(vrc))
170 *phmod = hmod;
171 else
172 {
173 if (vrc != VERR_SYMBOL_NOT_FOUND)
174 LogRel(("Resolving symbol '%s': %Rrc\n", s_szSymbol, vrc));
175 RTLdrClose(hmod);
176 hmod = NIL_RTLDRMOD;
177 }
178 }
179 else
180 {
181 LogRel(("Loading the library '%s': %Rrc\n", pszPath, vrc));
182 if (RTErrInfoIsSet(&ErrInfo.Core))
183 LogRel((" %s\n", ErrInfo.Core.pszMsg));
184 }
185 }
186 else
187 {
188 LogRel(("Loading the library '%s': No path! Refusing to try loading it!\n", pszPath));
189 vrc = VERR_INVALID_PARAMETER;
190 }
191 return vrc;
192}
193
194
195static HRESULT fillDeviceList(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
196{
197 Utf8Str strLibrary;
198#ifdef VBOX_WITH_EXTPACK
199 ExtPackManager *pExtPackMgr = pVirtualBox->i_getExtPackManager();
200 HRESULT hrc = pExtPackMgr->i_getLibraryPathForExtPack("VBoxHostWebcam", ORACLE_PUEL_EXTPACK_NAME, &strLibrary);
201#else
202 HRESULT hrc = E_NOTIMPL;
203#endif
204
205 if (SUCCEEDED(hrc))
206 {
207 PFNVBOXHOSTWEBCAMLIST pfn = NULL;
208 RTLDRMOD hmod = NIL_RTLDRMOD;
209#if CLANG_EXCEPTION_SPEC_HACK
210 int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, (void **)&pfn);
211#else
212 int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, &pfn);
213#endif
214
215 LogRel(("Load [%s] vrc=%Rrc\n", strLibrary.c_str(), vrc));
216
217 if (RT_SUCCESS(vrc))
218 {
219 uint64_t u64Result = S_OK;
220 vrc = pfn(hostWebcamAdd, pList, &u64Result);
221 Log(("VBoxHostWebcamList vrc %Rrc, result 0x%08RX64\n", vrc, u64Result));
222 if (RT_FAILURE(vrc))
223 hrc = (HRESULT)u64Result;
224
225 RTLdrClose(hmod);
226 hmod = NIL_RTLDRMOD;
227 }
228
229 if (SUCCEEDED(hrc))
230 {
231 if (RT_FAILURE(vrc))
232 hrc = pVirtualBox->setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
233 HostVideoInputDevice::tr("Failed to get webcam list: %Rrc"), vrc);
234 }
235 }
236
237 return hrc;
238}
239
240/* static */ HRESULT HostVideoInputDevice::queryHostDevices(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
241{
242 HRESULT hrc = fillDeviceList(pVirtualBox, pList);
243 if (FAILED(hrc))
244 pList->clear();
245 return hrc;
246}
247
248/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use