summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
commit16f504a9dca3fe3b70568f67b7d41241ae485288 (patch)
treec60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp
parentInitial commit. (diff)
downloadvirtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.tar.xz
virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.zip
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp')
-rw-r--r--src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp b/src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp
new file mode 100644
index 00000000..8c2eae53
--- /dev/null
+++ b/src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp
@@ -0,0 +1,256 @@
+/* $Id: HostVideoInputDeviceImpl.cpp $ */
+/** @file
+ * Host video capture device implementation.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#define LOG_GROUP LOG_GROUP_MAIN_HOSTVIDEOINPUTDEVICE
+#include "HostVideoInputDeviceImpl.h"
+#include "LoggingNew.h"
+#include "VirtualBoxImpl.h"
+#ifdef VBOX_WITH_EXTPACK
+# include "ExtPackManagerImpl.h"
+#endif
+
+#include <iprt/err.h>
+#include <iprt/ldr.h>
+#include <iprt/path.h>
+
+#include <VBox/sup.h>
+
+/*
+ * HostVideoInputDevice implementation.
+ */
+DEFINE_EMPTY_CTOR_DTOR(HostVideoInputDevice)
+
+HRESULT HostVideoInputDevice::FinalConstruct()
+{
+ return BaseFinalConstruct();
+}
+
+void HostVideoInputDevice::FinalRelease()
+{
+ uninit();
+
+ BaseFinalRelease();
+}
+
+/*
+ * Initializes the instance.
+ */
+HRESULT HostVideoInputDevice::init(const com::Utf8Str &name, const com::Utf8Str &path, const com::Utf8Str &alias)
+{
+ LogFlowThisFunc(("\n"));
+
+ /* Enclose the state transition NotReady->InInit->Ready */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+ m.name = name;
+ m.path = path;
+ m.alias = alias;
+
+ /* Confirm a successful initialization */
+ autoInitSpan.setSucceeded();
+
+ return S_OK;
+}
+
+/*
+ * Uninitializes the instance.
+ * Called either from FinalRelease() or by the parent when it gets destroyed.
+ */
+void HostVideoInputDevice::uninit()
+{
+ LogFlowThisFunc(("\n"));
+
+ /* Enclose the state transition Ready->InUninit->NotReady */
+ AutoUninitSpan autoUninitSpan(this);
+ if (autoUninitSpan.uninitDone())
+ return;
+
+ m.name.setNull();
+ m.path.setNull();
+ m.alias.setNull();
+}
+
+static HRESULT hostVideoInputDeviceAdd(HostVideoInputDeviceList *pList,
+ const com::Utf8Str &name,
+ const com::Utf8Str &path,
+ const com::Utf8Str &alias)
+{
+ ComObjPtr<HostVideoInputDevice> obj;
+ HRESULT hr = obj.createObject();
+ if (SUCCEEDED(hr))
+ {
+ hr = obj->init(name, path, alias);
+ if (SUCCEEDED(hr))
+ pList->push_back(obj);
+ }
+ return hr;
+}
+
+static DECLCALLBACK(int) hostWebcamAdd(void *pvUser,
+ const char *pszName,
+ const char *pszPath,
+ const char *pszAlias,
+ uint64_t *pu64Result)
+{
+ HostVideoInputDeviceList *pList = (HostVideoInputDeviceList *)pvUser;
+ HRESULT hr = hostVideoInputDeviceAdd(pList, pszName, pszPath, pszAlias);
+ if (FAILED(hr))
+ {
+ *pu64Result = (uint64_t)hr;
+ return VERR_NOT_SUPPORTED;
+ }
+ return VINF_SUCCESS;
+}
+
+/** @todo These typedefs must be in a header. */
+typedef DECLCALLBACKTYPE(int, FNVBOXHOSTWEBCAMADD,(void *pvUser,
+ const char *pszName,
+ const char *pszPath,
+ const char *pszAlias,
+ uint64_t *pu64Result));
+typedef FNVBOXHOSTWEBCAMADD *PFNVBOXHOSTWEBCAMADD;
+
+typedef DECLCALLBACKTYPE(int, FNVBOXHOSTWEBCAMLIST,(PFNVBOXHOSTWEBCAMADD pfnWebcamAdd,
+ void *pvUser,
+ uint64_t *pu64WebcamAddResult));
+typedef FNVBOXHOSTWEBCAMLIST *PFNVBOXHOSTWEBCAMLIST;
+
+
+/*
+ * Work around clang being unhappy about PFNVBOXHOSTWEBCAMLIST
+ * ("exception specifications are not allowed beyond a single level of
+ * indirection"). The original comment for 13.0 check said: "assuming
+ * this issue will be fixed eventually". Well, 13.0 is now out, and
+ * it was not.
+ */
+#define CLANG_EXCEPTION_SPEC_HACK (RT_CLANG_PREREQ(11, 0) /* && !RT_CLANG_PREREQ(13, 0) */)
+
+#if CLANG_EXCEPTION_SPEC_HACK
+static int loadHostWebcamLibrary(const char *pszPath, RTLDRMOD *phmod, void **ppfn)
+#else
+static int loadHostWebcamLibrary(const char *pszPath, RTLDRMOD *phmod, PFNVBOXHOSTWEBCAMLIST *ppfn)
+#endif
+{
+ int rc;
+ if (RTPathHavePath(pszPath))
+ {
+ RTLDRMOD hmod = NIL_RTLDRMOD;
+ RTERRINFOSTATIC ErrInfo;
+ rc = SUPR3HardenedLdrLoadPlugIn(pszPath, &hmod, RTErrInfoInitStatic(&ErrInfo));
+ if (RT_SUCCESS(rc))
+ {
+ static const char s_szSymbol[] = "VBoxHostWebcamList";
+ rc = RTLdrGetSymbol(hmod, s_szSymbol, (void **)ppfn);
+ if (RT_SUCCESS(rc))
+ *phmod = hmod;
+ else
+ {
+ if (rc != VERR_SYMBOL_NOT_FOUND)
+ LogRel(("Resolving symbol '%s': %Rrc\n", s_szSymbol, rc));
+ RTLdrClose(hmod);
+ hmod = NIL_RTLDRMOD;
+ }
+ }
+ else
+ {
+ LogRel(("Loading the library '%s': %Rrc\n", pszPath, rc));
+ if (RTErrInfoIsSet(&ErrInfo.Core))
+ LogRel((" %s\n", ErrInfo.Core.pszMsg));
+ }
+ }
+ else
+ {
+ LogRel(("Loading the library '%s': No path! Refusing to try loading it!\n", pszPath));
+ rc = VERR_INVALID_PARAMETER;
+ }
+ return rc;
+}
+
+
+static HRESULT fillDeviceList(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
+{
+ HRESULT hr;
+ Utf8Str strLibrary;
+
+#ifdef VBOX_WITH_EXTPACK
+ ExtPackManager *pExtPackMgr = pVirtualBox->i_getExtPackManager();
+ hr = pExtPackMgr->i_getLibraryPathForExtPack("VBoxHostWebcam", ORACLE_PUEL_EXTPACK_NAME, &strLibrary);
+#else
+ hr = E_NOTIMPL;
+#endif
+
+ if (SUCCEEDED(hr))
+ {
+ PFNVBOXHOSTWEBCAMLIST pfn = NULL;
+ RTLDRMOD hmod = NIL_RTLDRMOD;
+#if CLANG_EXCEPTION_SPEC_HACK
+ int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, (void **)&pfn);
+#else
+ int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, &pfn);
+#endif
+
+ LogRel(("Load [%s] vrc=%Rrc\n", strLibrary.c_str(), vrc));
+
+ if (RT_SUCCESS(vrc))
+ {
+ uint64_t u64Result = S_OK;
+ vrc = pfn(hostWebcamAdd, pList, &u64Result);
+ Log(("VBoxHostWebcamList vrc %Rrc, result 0x%08RX64\n", vrc, u64Result));
+ if (RT_FAILURE(vrc))
+ {
+ hr = (HRESULT)u64Result;
+ }
+
+ RTLdrClose(hmod);
+ hmod = NIL_RTLDRMOD;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (RT_FAILURE(vrc))
+ hr = pVirtualBox->setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
+ HostVideoInputDevice::tr("Failed to get webcam list: %Rrc"), vrc);
+ }
+ }
+
+ return hr;
+}
+
+/* static */ HRESULT HostVideoInputDevice::queryHostDevices(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
+{
+ HRESULT hr = fillDeviceList(pVirtualBox, pList);
+
+ if (FAILED(hr))
+ {
+ pList->clear();
+ }
+
+ return hr;
+}
+
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */