VirtualBox

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

Last change on this file since 93533 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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