akvirtualcamera/cmio/VirtualCamera/src/plugininterface.cpp

976 lines
36 KiB
C++

/* akvirtualcamera, virtual camera for Mac and Windows.
* Copyright (C) 2020 Gonzalo Exequiel Pedone
*
* akvirtualcamera 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, either version 3 of the License, or
* (at your option) any later version.
*
* akvirtualcamera 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 akvirtualcamera. If not, see <http://www.gnu.org/licenses/>.
*
* Web-Site: http://webcamoid.github.io/
*/
#include <sstream>
#include <algorithm>
#include <sys/stat.h>
#include <IOKit/audio/IOAudioTypes.h>
#include "plugininterface.h"
#include "Assistant/src/assistantglobals.h"
#include "PlatformUtils/src/preferences.h"
#include "PlatformUtils/src/utils.h"
#include "VCamUtils/src/videoformat.h"
#include "VCamUtils/src/ipcbridge.h"
#include "VCamUtils/src/logger.h"
namespace AkVCam
{
struct PluginInterfacePrivate
{
public:
CMIOHardwarePlugInInterface *pluginInterface;
PluginInterface *self;
ULONG m_ref;
ULONG m_reserved;
IpcBridge m_ipcBridge {true};
void updateDevices();
static HRESULT QueryInterface(void *self,
REFIID uuid,
LPVOID *interface);
static ULONG AddRef(void *self);
static ULONG Release(void *self);
static OSStatus Initialize(CMIOHardwarePlugInRef self);
static OSStatus InitializeWithObjectID(CMIOHardwarePlugInRef self,
CMIOObjectID objectID);
static OSStatus Teardown(CMIOHardwarePlugInRef self);
static void ObjectShow(CMIOHardwarePlugInRef self,
CMIOObjectID objectID);
static Boolean ObjectHasProperty(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address);
static OSStatus ObjectIsPropertySettable(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
Boolean *isSettable);
static OSStatus ObjectGetPropertyDataSize(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
UInt32 qualifierDataSize,
const void *qualifierData,
UInt32 *dataSize);
static OSStatus ObjectGetPropertyData(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
UInt32 qualifierDataSize,
const void *qualifierData,
UInt32 dataSize,
UInt32 *dataUsed,
void *data);
static OSStatus ObjectSetPropertyData(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
UInt32 qualifierDataSize,
const void *qualifierData,
UInt32 dataSize,
const void *data);
static OSStatus DeviceSuspend(CMIOHardwarePlugInRef self,
CMIODeviceID device);
static OSStatus DeviceResume(CMIOHardwarePlugInRef self,
CMIODeviceID device);
static OSStatus DeviceStartStream(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIOStreamID stream);
static OSStatus DeviceStopStream(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIOStreamID stream);
static OSStatus DeviceProcessAVCCommand(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIODeviceAVCCommand *ioAVCCommand);
static OSStatus DeviceProcessRS422Command(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIODeviceRS422Command *ioRS422Command);
static OSStatus StreamCopyBufferQueue(CMIOHardwarePlugInRef self,
CMIOStreamID stream,
CMIODeviceStreamQueueAlteredProc queueAlteredProc,
void *queueAlteredRefCon,
CMSimpleQueueRef *queue);
static OSStatus StreamDeckPlay(CMIOHardwarePlugInRef self,
CMIOStreamID stream);
static OSStatus StreamDeckStop(CMIOHardwarePlugInRef self,
CMIOStreamID stream);
static OSStatus StreamDeckJog(CMIOHardwarePlugInRef self,
CMIOStreamID stream,
SInt32 speed);
static OSStatus StreamDeckCueTo(CMIOHardwarePlugInRef self,
CMIOStreamID stream,
Float64 frameNumber,
Boolean playOnCue);
};
}
AkVCam::PluginInterface::PluginInterface():
ObjectInterface(),
m_objectID(0)
{
this->m_className = "PluginInterface";
this->d = new PluginInterfacePrivate;
this->d->self = this;
this->d->pluginInterface = new CMIOHardwarePlugInInterface {
// Padding for COM
NULL,
// IUnknown Routines
PluginInterfacePrivate::QueryInterface,
PluginInterfacePrivate::AddRef,
PluginInterfacePrivate::Release,
// DAL Plug-In Routines
PluginInterfacePrivate::Initialize,
PluginInterfacePrivate::InitializeWithObjectID,
PluginInterfacePrivate::Teardown,
PluginInterfacePrivate::ObjectShow,
PluginInterfacePrivate::ObjectHasProperty,
PluginInterfacePrivate::ObjectIsPropertySettable,
PluginInterfacePrivate::ObjectGetPropertyDataSize,
PluginInterfacePrivate::ObjectGetPropertyData,
PluginInterfacePrivate::ObjectSetPropertyData,
PluginInterfacePrivate::DeviceSuspend,
PluginInterfacePrivate::DeviceResume,
PluginInterfacePrivate::DeviceStartStream,
PluginInterfacePrivate::DeviceStopStream,
PluginInterfacePrivate::DeviceProcessAVCCommand,
PluginInterfacePrivate::DeviceProcessRS422Command,
PluginInterfacePrivate::StreamCopyBufferQueue,
PluginInterfacePrivate::StreamDeckPlay,
PluginInterfacePrivate::StreamDeckStop,
PluginInterfacePrivate::StreamDeckJog,
PluginInterfacePrivate::StreamDeckCueTo
};
this->d->m_ref = 0;
this->d->m_reserved = 0;
this->d->m_ipcBridge.connectServerStateChanged(this, &PluginInterface::serverStateChanged);
this->d->m_ipcBridge.connectDevicesChanged(this, &PluginInterface::devicesChanged);
this->d->m_ipcBridge.connectFrameReady(this, &PluginInterface::frameReady);
this->d->m_ipcBridge.connectPictureChanged(this, &PluginInterface::pictureChanged);
this->d->m_ipcBridge.connectBroadcastingChanged(this, &PluginInterface::setBroadcasting);
this->d->m_ipcBridge.connectControlsChanged(this, &PluginInterface::controlsChanged);
}
AkVCam::PluginInterface::~PluginInterface()
{
delete this->d->pluginInterface;
delete this->d;
}
CMIOObjectID AkVCam::PluginInterface::objectID() const
{
return this->m_objectID;
}
CMIOHardwarePlugInRef AkVCam::PluginInterface::create()
{
AkLogFunction();
auto pluginInterface = new PluginInterface();
pluginInterface->d->AddRef(pluginInterface->d);
return reinterpret_cast<CMIOHardwarePlugInRef>(pluginInterface->d);
}
AkVCam::Object *AkVCam::PluginInterface::findObject(CMIOObjectID objectID)
{
for (auto device: this->m_devices)
if (auto object = device->findObject(objectID))
return object;
return nullptr;
}
HRESULT AkVCam::PluginInterface::QueryInterface(REFIID uuid, LPVOID *interface)
{
AkLogFunction();
if (!interface)
return E_POINTER;
if (uuidEqual(uuid, kCMIOHardwarePlugInInterfaceID)
|| uuidEqual(uuid, IUnknownUUID)) {
AkLogInfo() << "Found plugin interface." << std::endl;
this->d->AddRef(this->d);
*interface = this->d;
return S_OK;
}
return E_NOINTERFACE;
}
OSStatus AkVCam::PluginInterface::Initialize()
{
AkLogFunction();
return this->InitializeWithObjectID(kCMIOObjectUnknown);
}
OSStatus AkVCam::PluginInterface::InitializeWithObjectID(CMIOObjectID objectID)
{
AkLogFunction();
AkLogInfo() << objectID << std::endl;
this->m_objectID = objectID;
for (auto &deviceId: this->d->m_ipcBridge.devices()) {
auto description = this->d->m_ipcBridge.description(deviceId);
auto formats = this->d->m_ipcBridge.formats(deviceId);
this->createDevice(deviceId, description, formats);
}
return kCMIOHardwareNoError;
}
OSStatus AkVCam::PluginInterface::Teardown()
{
AkLogFunction();
std::vector<std::string> oldDevices;
for (auto &device: this->m_devices) {
std::string deviceId;
device->properties().getProperty(kCMIODevicePropertyDeviceUID,
&deviceId);
oldDevices.push_back(deviceId);
}
for (auto &deviceId: oldDevices)
this->destroyDevice(deviceId);
return kCMIOHardwareNoError;
}
void AkVCam::PluginInterface::serverStateChanged(void *userData,
IpcBridge::ServerState state)
{
AkLogFunction();
auto self = reinterpret_cast<PluginInterface *>(userData);
for (auto device: self->m_devices)
device->serverStateChanged(state);
if (state == IpcBridge::ServerStateAvailable)
self->d->updateDevices();
}
void AkVCam::PluginInterface::devicesChanged(void *userData,
const std::vector<std::string> &devices)
{
UNUSED(devices);
AkLogFunction();
auto self = reinterpret_cast<PluginInterface *>(userData);
std::vector<std::string> oldDevices;
for (auto &device: self->m_devices) {
std::string deviceId;
device->properties().getProperty(kCMIODevicePropertyDeviceUID,
&deviceId);
oldDevices.push_back(deviceId);
}
for (auto &deviceId: oldDevices)
self->destroyDevice(deviceId);
for (auto &deviceId: self->d->m_ipcBridge.devices()) {
auto description = self->d->m_ipcBridge.description(deviceId);
auto formats = self->d->m_ipcBridge.formats(deviceId);
self->createDevice(deviceId, description, formats);
}
}
void AkVCam::PluginInterface::frameReady(void *userData,
const std::string &deviceId,
const VideoFrame &frame)
{
AkLogFunction();
auto self = reinterpret_cast<PluginInterface *>(userData);
for (auto device: self->m_devices)
if (device->deviceId() == deviceId)
device->frameReady(frame);
}
void AkVCam::PluginInterface::pictureChanged(void *userData,
const std::string &picture)
{
AkLogFunction();
auto self = reinterpret_cast<PluginInterface *>(userData);
for (auto device: self->m_devices)
device->setPicture(picture);
}
void AkVCam::PluginInterface::setBroadcasting(void *userData,
const std::string &deviceId,
const std::string &broadcaster)
{
AkLogFunction();
AkLogInfo() << "Device: " << deviceId << std::endl;
AkLogInfo() << "Broadcaster: " << broadcaster << std::endl;
auto self = reinterpret_cast<PluginInterface *>(userData);
for (auto device: self->m_devices)
if (device->deviceId() == deviceId)
device->setBroadcasting(broadcaster);
}
void AkVCam::PluginInterface::controlsChanged(void *userData,
const std::string &deviceId,
const std::map<std::string, int> &controls)
{
AkLogFunction();
AkLogInfo() << "Device: " << deviceId << std::endl;
auto self = reinterpret_cast<PluginInterface *>(userData);
for (auto device: self->m_devices)
if (device->deviceId() == deviceId) {
if (controls.count("hflip"))
device->setHorizontalMirror(controls.at("hflip"));
if (controls.count("vflip"))
device->setVerticalMirror(controls.at("vflip"));
if (controls.count("scaling"))
device->setScaling(Scaling(controls.at("scaling")));
if (controls.count("aspect_ratio"))
device->setAspectRatio(AspectRatio(controls.at("aspect_ratio")));
if (controls.count("swap_rgb"))
device->setSwapRgb(controls.at("swap_rgb"));
}
}
void AkVCam::PluginInterface::addListener(void *userData,
const std::string &deviceId)
{
AkLogFunction();
auto self = reinterpret_cast<PluginInterface *>(userData);
self->d->m_ipcBridge.addListener(deviceId);
}
void AkVCam::PluginInterface::removeListener(void *userData,
const std::string &deviceId)
{
AkLogFunction();
auto self = reinterpret_cast<PluginInterface *>(userData);
self->d->m_ipcBridge.removeListener(deviceId);
}
bool AkVCam::PluginInterface::createDevice(const std::string &deviceId,
const std::string &description,
const std::vector<VideoFormat> &formats)
{
AkLogFunction();
StreamPtr stream;
// Create one device.
auto pluginRef = reinterpret_cast<CMIOHardwarePlugInRef>(this->d);
auto device = std::make_shared<Device>(pluginRef, false);
device->setDeviceId(deviceId);
device->connectAddListener(this, &PluginInterface::addListener);
device->connectRemoveListener(this, &PluginInterface::removeListener);
this->m_devices.push_back(device);
auto cameraIndex = Preferences::cameraFromPath(deviceId);
auto hflip = Preferences::cameraControlValue(cameraIndex, "hflip");
auto vflip = Preferences::cameraControlValue(cameraIndex, "vflip");
auto scaling = Preferences::cameraControlValue(cameraIndex, "scaling");
auto aspectRatio = Preferences::cameraControlValue(cameraIndex, "aspect_ratio");
auto swapRgb = Preferences::cameraControlValue(cameraIndex, "swap_rgb");
// Define device properties.
device->properties().setProperty(kCMIOObjectPropertyName,
description);
device->properties().setProperty(kCMIOObjectPropertyManufacturer,
CMIO_PLUGIN_VENDOR);
device->properties().setProperty(kCMIODevicePropertyModelUID,
CMIO_PLUGIN_PRODUCT);
device->properties().setProperty(kCMIODevicePropertyLinkedCoreAudioDeviceUID,
"");
device->properties().setProperty(kCMIODevicePropertyLinkedAndSyncedCoreAudioDeviceUID,
"");
device->properties().setProperty(kCMIODevicePropertySuspendedByUser,
UInt32(0));
device->properties().setProperty(kCMIODevicePropertyHogMode,
pid_t(-1),
false);
device->properties().setProperty(kCMIODevicePropertyDeviceMaster,
pid_t(-1));
device->properties().setProperty(kCMIODevicePropertyExcludeNonDALAccess,
UInt32(0));
device->properties().setProperty(kCMIODevicePropertyDeviceIsAlive,
UInt32(1));
device->properties().setProperty(kCMIODevicePropertyDeviceUID,
deviceId);
device->properties().setProperty(kCMIODevicePropertyTransportType,
UInt32(kIOAudioDeviceTransportTypePCI));
device->properties().setProperty(kCMIODevicePropertyDeviceIsRunningSomewhere,
UInt32(0));
if (device->createObject() != kCMIOHardwareNoError)
goto createDevice_failed;
stream = device->addStream();
// Register one stream for this device.
if (!stream)
goto createDevice_failed;
stream->setBridge(&this->d->m_ipcBridge);
stream->setFormats(formats);
stream->properties().setProperty(kCMIOStreamPropertyDirection, 0);
if (device->registerStreams() != kCMIOHardwareNoError) {
AkLogDebug() << "Failed registering streams" << std::endl;
device->registerStreams(false);
goto createDevice_failed;
}
// Register the device.
if (device->registerObject() != kCMIOHardwareNoError) {
AkLogDebug() << "Failed registering device" << std::endl;
device->registerObject(false);
device->registerStreams(false);
goto createDevice_failed;
}
device->setBroadcasting(this->d->m_ipcBridge.broadcaster(deviceId));
device->setHorizontalMirror(hflip);
device->setVerticalMirror(vflip);
device->setScaling(Scaling(scaling));
device->setAspectRatio(AspectRatio(aspectRatio));
device->setSwapRgb(swapRgb);
return true;
createDevice_failed:
this->m_devices.erase(std::prev(this->m_devices.end()));
return false;
}
void AkVCam::PluginInterface::destroyDevice(const std::string &deviceId)
{
AkLogFunction();
for (auto it = this->m_devices.begin(); it != this->m_devices.end(); it++) {
auto device = *it;
std::string curDeviceId;
device->properties().getProperty(kCMIODevicePropertyDeviceUID,
&curDeviceId);
if (curDeviceId == deviceId) {
device->stopStreams();
device->registerObject(false);
device->registerStreams(false);
this->m_devices.erase(it);
break;
}
}
}
void AkVCam::PluginInterfacePrivate::updateDevices()
{
for (auto &device: this->self->m_devices) {
device->setBroadcasting(this->m_ipcBridge.broadcaster(device->deviceId()));
auto cameraIndex = Preferences::cameraFromPath(device->deviceId());
auto hflip = Preferences::cameraControlValue(cameraIndex, "hflip");
auto vflip = Preferences::cameraControlValue(cameraIndex, "vflip");
auto scaling = Preferences::cameraControlValue(cameraIndex, "scaling");
auto aspectRatio = Preferences::cameraControlValue(cameraIndex, "aspect_ratio");
auto swapRgb = Preferences::cameraControlValue(cameraIndex, "swap_rgb");
device->setHorizontalMirror(hflip);
device->setVerticalMirror(vflip);
device->setScaling(Scaling(scaling));
device->setAspectRatio(AspectRatio(aspectRatio));
device->setSwapRgb(swapRgb);
}
}
HRESULT AkVCam::PluginInterfacePrivate::QueryInterface(void *self,
REFIID uuid,
LPVOID *interface)
{
AkLogFunction();
if (!self)
return E_FAIL;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
return _self->self->QueryInterface(uuid, interface);
}
ULONG AkVCam::PluginInterfacePrivate::AddRef(void *self)
{
AkLogFunction();
if (!self)
return 0;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
_self->m_ref++;
return _self->m_ref;
}
ULONG AkVCam::PluginInterfacePrivate::Release(void *self)
{
AkLogFunction();
if (!self)
return 0;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
if (_self->m_ref > 0) {
_self->m_ref--;
if (_self->m_ref < 1) {
delete _self->self;
return 0UL;
}
}
return _self->m_ref;
}
OSStatus AkVCam::PluginInterfacePrivate::Initialize(CMIOHardwarePlugInRef self)
{
AkLogFunction();
if (!self)
return kCMIOHardwareUnspecifiedError;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
return _self->self->Initialize();
}
OSStatus AkVCam::PluginInterfacePrivate::InitializeWithObjectID(CMIOHardwarePlugInRef self,
CMIOObjectID objectID)
{
AkLogFunction();
if (!self)
return kCMIOHardwareUnspecifiedError;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
return _self->self->InitializeWithObjectID(objectID);
}
OSStatus AkVCam::PluginInterfacePrivate::Teardown(CMIOHardwarePlugInRef self)
{
AkLogFunction();
if (!self)
return kCMIOHardwareUnspecifiedError;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
return _self->self->Teardown();
}
void AkVCam::PluginInterfacePrivate::ObjectShow(CMIOHardwarePlugInRef self,
CMIOObjectID objectID)
{
AkLogFunction();
AkLogInfo() << "ObjectID " << objectID << std::endl;
if (!self)
return;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
if (_self->self->objectID() == objectID)
_self->self->show();
else if (auto object = _self->self->findObject(objectID))
object->show();
}
Boolean AkVCam::PluginInterfacePrivate::ObjectHasProperty(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address)
{
AkLogFunction();
AkLogInfo() << "ObjectID " << objectID << std::endl;
Boolean result = false;
if (!self)
return result;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
if (_self->self->objectID() == objectID)
result = _self->self->hasProperty(address);
else if (auto object = _self->self->findObject(objectID))
result = object->hasProperty(address);
return result;
}
OSStatus AkVCam::PluginInterfacePrivate::ObjectIsPropertySettable(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
Boolean *isSettable)
{
AkLogFunction();
AkLogInfo() << "ObjectID " << objectID << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
if (_self->self->objectID() == objectID)
status = _self->self->isPropertySettable(address,
isSettable);
else if (auto object = _self->self->findObject(objectID))
status = object->isPropertySettable(address,
isSettable);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::ObjectGetPropertyDataSize(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
UInt32 qualifierDataSize,
const void *qualifierData,
UInt32 *dataSize)
{
AkLogFunction();
AkLogInfo() << "ObjectID " << objectID << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
if (_self->self->objectID() == objectID)
status = _self->self->getPropertyDataSize(address,
qualifierDataSize,
qualifierData,
dataSize);
else if (auto object = _self->self->findObject(objectID))
status = object->getPropertyDataSize(address,
qualifierDataSize,
qualifierData,
dataSize);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::ObjectGetPropertyData(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
UInt32 qualifierDataSize,
const void *qualifierData,
UInt32 dataSize,
UInt32 *dataUsed,
void *data)
{
AkLogFunction();
AkLogInfo() << "ObjectID " << objectID << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
if (_self->self->objectID() == objectID)
status = _self->self->getPropertyData(address,
qualifierDataSize,
qualifierData,
dataSize,
dataUsed,
data);
else if (auto object = _self->self->findObject(objectID))
status = object->getPropertyData(address,
qualifierDataSize,
qualifierData,
dataSize,
dataUsed,
data);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::ObjectSetPropertyData(CMIOHardwarePlugInRef self,
CMIOObjectID objectID,
const CMIOObjectPropertyAddress *address,
UInt32 qualifierDataSize,
const void *qualifierData,
UInt32 dataSize,
const void *data)
{
AkLogFunction();
AkLogInfo() << "ObjectID " << objectID << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
if (_self->self->objectID() == objectID)
status = _self->self->setPropertyData(address,
qualifierDataSize,
qualifierData,
dataSize,
data);
else if (auto object = _self->self->findObject(objectID))
status = object->setPropertyData(address,
qualifierDataSize,
qualifierData,
dataSize,
data);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::DeviceSuspend(CMIOHardwarePlugInRef self,
CMIODeviceID device)
{
AkLogFunction();
AkLogInfo() << "DeviceID " << device << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Device *>(_self->self->findObject(device));
if (object)
status = object->suspend();
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::DeviceResume(CMIOHardwarePlugInRef self,
CMIODeviceID device)
{
AkLogFunction();
AkLogInfo() << "DeviceID " << device << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Device *>(_self->self->findObject(device));
if (object)
status = object->resume();
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::DeviceStartStream(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIOStreamID stream)
{
AkLogFunction();
AkLogInfo() << "DeviceID " << device << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Device *>(_self->self->findObject(device));
if (object)
status = object->startStream(stream);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::DeviceStopStream(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIOStreamID stream)
{
AkLogFunction();
AkLogInfo() << "DeviceID " << device << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Device *>(_self->self->findObject(device));
if (object)
status = object->stopStream(stream);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::DeviceProcessAVCCommand(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIODeviceAVCCommand *ioAVCCommand)
{
AkLogFunction();
AkLogInfo() << "DeviceID " << device << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Device *>(_self->self->findObject(device));
if (object)
status = object->processAVCCommand(ioAVCCommand);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::DeviceProcessRS422Command(CMIOHardwarePlugInRef self,
CMIODeviceID device,
CMIODeviceRS422Command *ioRS422Command)
{
AkLogFunction();
AkLogInfo() << "DeviceID " << device << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Device *>(_self->self->findObject(device));
if (object)
status = object->processRS422Command(ioRS422Command);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::StreamCopyBufferQueue(CMIOHardwarePlugInRef self,
CMIOStreamID stream,
CMIODeviceStreamQueueAlteredProc queueAlteredProc,
void *queueAlteredRefCon,
CMSimpleQueueRef *queue)
{
AkLogFunction();
AkLogInfo() << "StreamID " << stream << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Stream *>(_self->self->findObject(stream));
if (object)
status = object->copyBufferQueue(queueAlteredProc,
queueAlteredRefCon,
queue);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::StreamDeckPlay(CMIOHardwarePlugInRef self,
CMIOStreamID stream)
{
AkLogFunction();
AkLogInfo() << "StreamID " << stream << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Stream *>(_self->self->findObject(stream));
if (object)
status = object->deckPlay();
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::StreamDeckStop(CMIOHardwarePlugInRef self,
CMIOStreamID stream)
{
AkLogFunction();
AkLogInfo() << "StreamID " << stream << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Stream *>(_self->self->findObject(stream));
if (object)
status = object->deckStop();
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::StreamDeckJog(CMIOHardwarePlugInRef self,
CMIOStreamID stream,
SInt32 speed)
{
AkLogFunction();
AkLogInfo() << "StreamID " << stream << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Stream *>(_self->self->findObject(stream));
if (object)
status = object->deckJog(speed);
return status;
}
OSStatus AkVCam::PluginInterfacePrivate::StreamDeckCueTo(CMIOHardwarePlugInRef self,
CMIOStreamID stream,
Float64 frameNumber,
Boolean playOnCue)
{
AkLogFunction();
AkLogInfo() << "StreamID " << stream << std::endl;
OSStatus status = kCMIOHardwareUnspecifiedError;
if (!self)
return status;
auto _self = reinterpret_cast<PluginInterfacePrivate *>(self);
auto object = reinterpret_cast<Stream *>(_self->self->findObject(stream));
if (object)
status = object->deckCueTo(frameNumber, playOnCue);
return status;
}