VirtualBox

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

Last change on this file since 98073 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: HostVideoInputDeviceImpl.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * Host video capture device implementation.
4 */
5
6/*
7 * Copyright (C) 2013-2022 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 hr = obj.createObject();
105 if (SUCCEEDED(hr))
106 {
107 hr = obj->init(name, path, alias);
108 if (SUCCEEDED(hr))
109 pList->push_back(obj);
110 }
111 return hr;
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 hr = hostVideoInputDeviceAdd(pList, pszName, pszPath, pszAlias);
122 if (FAILED(hr))
123 {
124 *pu64Result = (uint64_t)hr;
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 rc;
160 if (RTPathHavePath(pszPath))
161 {
162 RTLDRMOD hmod = NIL_RTLDRMOD;
163 RTERRINFOSTATIC ErrInfo;
164 rc = SUPR3HardenedLdrLoadPlugIn(pszPath, &hmod, RTErrInfoInitStatic(&ErrInfo));
165 if (RT_SUCCESS(rc))
166 {
167 static const char s_szSymbol[] = "VBoxHostWebcamList";
168 rc = RTLdrGetSymbol(hmod, s_szSymbol, (void **)ppfn);
169 if (RT_SUCCESS(rc))
170 *phmod = hmod;
171 else
172 {
173 if (rc != VERR_SYMBOL_NOT_FOUND)
174 LogRel(("Resolving symbol '%s': %Rrc\n", s_szSymbol, rc));
175 RTLdrClose(hmod);
176 hmod = NIL_RTLDRMOD;
177 }
178 }
179 else
180 {
181 LogRel(("Loading the library '%s': %Rrc\n", pszPath, rc));
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 rc = VERR_INVALID_PARAMETER;
190 }
191 return rc;
192}
193
194
195static HRESULT fillDeviceList(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
196{
197 HRESULT hr;
198 Utf8Str strLibrary;
199
200#ifdef VBOX_WITH_EXTPACK
201 ExtPackManager *pExtPackMgr = pVirtualBox->i_getExtPackManager();
202 hr = pExtPackMgr->i_getLibraryPathForExtPack("VBoxHostWebcam", ORACLE_PUEL_EXTPACK_NAME, &strLibrary);
203#else
204 hr = E_NOTIMPL;
205#endif
206
207 if (SUCCEEDED(hr))
208 {
209 PFNVBOXHOSTWEBCAMLIST pfn = NULL;
210 RTLDRMOD hmod = NIL_RTLDRMOD;
211#if CLANG_EXCEPTION_SPEC_HACK
212 int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, (void **)&pfn);
213#else
214 int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, &pfn);
215#endif
216
217 LogRel(("Load [%s] vrc=%Rrc\n", strLibrary.c_str(), vrc));
218
219 if (RT_SUCCESS(vrc))
220 {
221 uint64_t u64Result = S_OK;
222 vrc = pfn(hostWebcamAdd, pList, &u64Result);
223 Log(("VBoxHostWebcamList vrc %Rrc, result 0x%08RX64\n", vrc, u64Result));
224 if (RT_FAILURE(vrc))
225 {
226 hr = (HRESULT)u64Result;
227 }
228
229 RTLdrClose(hmod);
230 hmod = NIL_RTLDRMOD;
231 }
232
233 if (SUCCEEDED(hr))
234 {
235 if (RT_FAILURE(vrc))
236 hr = pVirtualBox->setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
237 HostVideoInputDevice::tr("Failed to get webcam list: %Rrc"), vrc);
238 }
239 }
240
241 return hr;
242}
243
244/* static */ HRESULT HostVideoInputDevice::queryHostDevices(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
245{
246 HRESULT hr = fillDeviceList(pVirtualBox, pList);
247
248 if (FAILED(hr))
249 {
250 pList->clear();
251 }
252
253 return hr;
254}
255
256/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette