2016-08-19 23:05:28 -07:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
/* Copyright (c) FIRST 2016. All Rights Reserved. */
|
|
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
2016-11-05 22:11:55 -07:00
|
|
|
#include "cscore_cpp.h"
|
2016-08-19 23:05:28 -07:00
|
|
|
|
2016-09-05 12:00:04 -07:00
|
|
|
#include "llvm/SmallString.h"
|
|
|
|
|
|
2016-11-05 13:13:09 -07:00
|
|
|
#include "Notifier.h"
|
2016-09-05 12:00:04 -07:00
|
|
|
#include "SinkImpl.h"
|
|
|
|
|
#include "SourceImpl.h"
|
|
|
|
|
#include "Handle.h"
|
2016-11-18 08:49:20 -08:00
|
|
|
#include "Notifier.h"
|
2016-08-19 23:05:28 -07:00
|
|
|
|
|
|
|
|
using namespace cs;
|
|
|
|
|
|
2016-09-05 12:00:04 -07:00
|
|
|
static std::shared_ptr<SourceImpl> GetPropertySource(CS_Property propertyHandle,
|
|
|
|
|
int* propertyIndex,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
Handle handle{propertyHandle};
|
2016-09-19 22:03:47 -07:00
|
|
|
int i = handle.GetParentIndex();
|
2016-09-05 12:00:04 -07:00
|
|
|
if (i < 0) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
auto data = Sources::GetInstance().Get(Handle{i, Handle::kSource});
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2016-09-19 22:03:47 -07:00
|
|
|
*propertyIndex = handle.GetIndex();
|
2016-09-05 12:00:04 -07:00
|
|
|
return data->source;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
namespace cs {
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Property Functions
|
|
|
|
|
//
|
|
|
|
|
|
2016-11-15 23:54:50 -08:00
|
|
|
CS_PropertyKind GetPropertyKind(CS_Property property, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return CS_PROP_NONE;
|
2016-11-15 23:54:50 -08:00
|
|
|
return source->GetPropertyKind(propertyIndex);
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-26 08:19:28 -07:00
|
|
|
std::string GetPropertyName(CS_Property property, CS_Status* status) {
|
2016-09-19 22:03:47 -07:00
|
|
|
llvm::SmallString<128> buf;
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return std::string{};
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetPropertyName(propertyIndex, buf, status);
|
2016-08-26 08:19:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::StringRef GetPropertyName(CS_Property property,
|
|
|
|
|
llvm::SmallVectorImpl<char>& buf,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
2016-09-10 21:30:39 -07:00
|
|
|
if (!source) return llvm::StringRef{};
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetPropertyName(propertyIndex, buf, status);
|
2016-08-26 08:19:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 22:17:12 -07:00
|
|
|
int GetProperty(CS_Property property, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return false;
|
2016-09-20 22:17:12 -07:00
|
|
|
return source->GetProperty(propertyIndex, status);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 22:17:12 -07:00
|
|
|
void SetProperty(CS_Property property, int value, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return;
|
2016-09-20 22:17:12 -07:00
|
|
|
source->SetProperty(propertyIndex, value, status);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 22:17:12 -07:00
|
|
|
int GetPropertyMin(CS_Property property, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return 0.0;
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetPropertyMin(propertyIndex, status);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 22:17:12 -07:00
|
|
|
int GetPropertyMax(CS_Property property, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return 0.0;
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetPropertyMax(propertyIndex, status);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 22:17:12 -07:00
|
|
|
int GetPropertyStep(CS_Property property, CS_Status* status) {
|
2016-09-16 21:00:19 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return 0.0;
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetPropertyStep(propertyIndex, status);
|
2016-09-16 21:00:19 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 22:17:12 -07:00
|
|
|
int GetPropertyDefault(CS_Property property, CS_Status* status) {
|
2016-09-16 21:00:19 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return 0.0;
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetPropertyDefault(propertyIndex, status);
|
2016-09-16 21:00:19 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
std::string GetStringProperty(CS_Property property, CS_Status* status) {
|
2016-09-19 23:50:47 -07:00
|
|
|
llvm::SmallString<128> buf;
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return std::string{};
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetStringProperty(propertyIndex, buf, status);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::StringRef GetStringProperty(CS_Property property,
|
|
|
|
|
llvm::SmallVectorImpl<char>& buf,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
2016-09-10 21:30:39 -07:00
|
|
|
if (!source) return llvm::StringRef{};
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetStringProperty(propertyIndex, buf, status);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
void SetStringProperty(CS_Property property, llvm::StringRef value,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return;
|
2016-09-19 23:50:47 -07:00
|
|
|
source->SetStringProperty(propertyIndex, value, status);
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> GetEnumPropertyChoices(CS_Property property,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
int propertyIndex;
|
|
|
|
|
auto source = GetPropertySource(property, &propertyIndex, status);
|
|
|
|
|
if (!source) return std::vector<std::string>{};
|
2016-09-19 23:50:47 -07:00
|
|
|
return source->GetEnumPropertyChoices(propertyIndex, status);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
//
|
|
|
|
|
// Source Creation Functions
|
|
|
|
|
//
|
|
|
|
|
|
2016-10-15 23:07:28 -07:00
|
|
|
CS_Source CreateHTTPCamera(llvm::StringRef name, llvm::StringRef url,
|
2016-08-25 23:13:48 -07:00
|
|
|
CS_Status* status) {
|
2016-08-19 23:05:28 -07:00
|
|
|
return 0; // TODO
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
//
|
|
|
|
|
// Source Functions
|
|
|
|
|
//
|
|
|
|
|
|
2016-11-15 23:54:50 -08:00
|
|
|
CS_SourceKind GetSourceKind(CS_Source source, CS_Status* status) {
|
2016-11-15 22:18:32 -08:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return CS_SOURCE_UNKNOWN;
|
|
|
|
|
}
|
2016-11-15 23:54:50 -08:00
|
|
|
return data->kind;
|
2016-11-15 22:18:32 -08:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
std::string GetSourceName(CS_Source source, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return std::string{};
|
|
|
|
|
}
|
|
|
|
|
return data->source->GetName();
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::StringRef GetSourceName(CS_Source source,
|
|
|
|
|
llvm::SmallVectorImpl<char>& buf,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
2016-09-10 21:30:39 -07:00
|
|
|
return llvm::StringRef{};
|
2016-09-05 12:00:04 -07:00
|
|
|
}
|
2016-09-10 21:30:39 -07:00
|
|
|
return data->source->GetName();
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
std::string GetSourceDescription(CS_Source source, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return std::string{};
|
|
|
|
|
}
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::SmallString<128> buf;
|
|
|
|
|
return data->source->GetDescription(buf);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::StringRef GetSourceDescription(CS_Source source,
|
|
|
|
|
llvm::SmallVectorImpl<char>& buf,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
2016-09-10 21:30:39 -07:00
|
|
|
return llvm::StringRef{};
|
2016-09-05 12:00:04 -07:00
|
|
|
}
|
2016-09-10 21:30:39 -07:00
|
|
|
return data->source->GetDescription(buf);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
uint64_t GetSourceLastFrameTime(CS_Source source, CS_Status* status) {
|
2016-10-22 22:09:47 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return data->source->GetCurFrameTime();
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
bool IsSourceConnected(CS_Source source, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return data->source->IsConnected();
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-26 09:24:18 -07:00
|
|
|
CS_Property GetSourceProperty(CS_Source source, llvm::StringRef name,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2016-09-20 22:17:12 -07:00
|
|
|
int property = data->source->GetPropertyIndex(name);
|
2016-09-05 12:00:04 -07:00
|
|
|
if (property < 0) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return Handle{source, property, Handle::kProperty};
|
2016-08-26 09:24:18 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::ArrayRef<CS_Property> EnumerateSourceProperties(
|
|
|
|
|
CS_Source source, llvm::SmallVectorImpl<CS_Property>& vec,
|
|
|
|
|
CS_Status* status) {
|
2016-09-19 22:03:47 -07:00
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
llvm::SmallVector<int, 32> properties_buf;
|
2016-10-13 00:16:24 -07:00
|
|
|
for (auto property :
|
|
|
|
|
data->source->EnumerateProperties(properties_buf, status))
|
2016-09-19 22:03:47 -07:00
|
|
|
vec.push_back(Handle{source, property, Handle::kProperty});
|
|
|
|
|
return vec;
|
2016-08-26 08:19:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-29 00:04:16 -07:00
|
|
|
VideoMode GetSourceVideoMode(CS_Source source, CS_Status* status) {
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return VideoMode{};
|
|
|
|
|
}
|
|
|
|
|
return data->source->GetVideoMode(status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SetSourceVideoMode(CS_Source source, const VideoMode& mode,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return data->source->SetVideoMode(mode, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SetSourcePixelFormat(CS_Source source, VideoMode::PixelFormat pixelFormat,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return data->source->SetPixelFormat(pixelFormat, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SetSourceResolution(CS_Source source, int width, int height,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return data->source->SetResolution(width, height, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SetSourceFPS(CS_Source source, int fps, CS_Status* status) {
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return data->source->SetFPS(fps, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<VideoMode> EnumerateSourceVideoModes(CS_Source source,
|
|
|
|
|
CS_Status* status) {
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return std::vector<VideoMode>{};
|
|
|
|
|
}
|
|
|
|
|
return data->source->EnumerateVideoModes(status);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-15 22:18:32 -08:00
|
|
|
llvm::ArrayRef<CS_Sink> EnumerateSourceSinks(
|
|
|
|
|
CS_Source source, llvm::SmallVectorImpl<CS_Sink>& vec, CS_Status* status) {
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return llvm::ArrayRef<CS_Sink>{};
|
|
|
|
|
}
|
|
|
|
|
vec.clear();
|
|
|
|
|
Sinks::GetInstance().ForEach([&](CS_Sink sinkHandle, const SinkData& data) {
|
|
|
|
|
if (source == data.sourceHandle.load()) vec.push_back(sinkHandle);
|
|
|
|
|
});
|
|
|
|
|
return vec;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
CS_Source CopySource(CS_Source source, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
if (source == 0) return 0;
|
|
|
|
|
auto data = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
data->refCount++;
|
|
|
|
|
return source;
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReleaseSource(CS_Source source, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
if (source == 0) return;
|
|
|
|
|
auto& inst = Sources::GetInstance();
|
|
|
|
|
auto data = inst.Get(source);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-11-18 08:49:20 -08:00
|
|
|
if (data->refCount-- == 0) {
|
|
|
|
|
Notifier::GetInstance().NotifySource(data->source->GetName(), source,
|
|
|
|
|
CS_SOURCE_DESTROYED);
|
|
|
|
|
inst.Free(source);
|
|
|
|
|
}
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Sink Functions
|
|
|
|
|
//
|
2016-10-26 23:37:00 -07:00
|
|
|
|
2016-11-15 23:54:50 -08:00
|
|
|
CS_SinkKind GetSinkKind(CS_Sink sink, CS_Status* status) {
|
2016-11-15 22:18:32 -08:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return CS_SINK_UNKNOWN;
|
|
|
|
|
}
|
2016-11-15 23:54:50 -08:00
|
|
|
return data->kind;
|
2016-11-15 22:18:32 -08:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
std::string GetSinkName(CS_Sink sink, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return std::string{};
|
|
|
|
|
}
|
|
|
|
|
return data->sink->GetName();
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::StringRef GetSinkName(CS_Sink sink, llvm::SmallVectorImpl<char>& buf,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
2016-09-10 21:30:39 -07:00
|
|
|
return llvm::StringRef{};
|
2016-09-05 12:00:04 -07:00
|
|
|
}
|
2016-09-10 21:30:39 -07:00
|
|
|
return data->sink->GetName();
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
std::string GetSinkDescription(CS_Sink sink, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return std::string{};
|
|
|
|
|
}
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::SmallString<128> buf;
|
|
|
|
|
return data->sink->GetDescription(buf);
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::StringRef GetSinkDescription(CS_Sink sink,
|
|
|
|
|
llvm::SmallVectorImpl<char>& buf,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
2016-09-10 21:30:39 -07:00
|
|
|
return llvm::StringRef{};
|
2016-09-05 12:00:04 -07:00
|
|
|
}
|
2016-09-10 21:30:39 -07:00
|
|
|
return data->sink->GetDescription(buf);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
void SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto sourceData = Sources::GetInstance().Get(source);
|
|
|
|
|
if (!sourceData) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
data->sink->SetSource(sourceData->source);
|
|
|
|
|
data->sourceHandle.store(source);
|
2016-11-18 08:56:24 -08:00
|
|
|
Notifier::GetInstance().NotifySinkSourceChanged(data->sink->GetName(), sink,
|
|
|
|
|
source);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
CS_Source GetSinkSource(CS_Sink sink, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return data->sourceHandle.load();
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-26 09:24:18 -07:00
|
|
|
CS_Property GetSinkSourceProperty(CS_Sink sink, llvm::StringRef name,
|
|
|
|
|
CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return GetSourceProperty(data->sourceHandle.load(), name, status);
|
2016-08-26 09:24:18 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
CS_Sink CopySink(CS_Sink sink, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
if (sink == 0) return 0;
|
|
|
|
|
auto data = Sinks::GetInstance().Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
data->refCount++;
|
|
|
|
|
return sink;
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
void ReleaseSink(CS_Sink sink, CS_Status* status) {
|
2016-09-05 12:00:04 -07:00
|
|
|
if (sink == 0) return;
|
|
|
|
|
auto& inst = Sinks::GetInstance();
|
|
|
|
|
auto data = inst.Get(sink);
|
|
|
|
|
if (!data) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-11-18 08:49:20 -08:00
|
|
|
if (data->refCount-- == 0) {
|
|
|
|
|
Notifier::GetInstance().NotifySink(data->sink->GetName(), sink,
|
|
|
|
|
CS_SINK_DESTROYED);
|
|
|
|
|
inst.Free(sink);
|
|
|
|
|
}
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
//
|
|
|
|
|
// Listener Functions
|
|
|
|
|
//
|
2016-08-19 23:05:28 -07:00
|
|
|
|
2016-11-05 13:13:09 -07:00
|
|
|
void SetListenerOnStart(std::function<void()> onStart) {
|
|
|
|
|
Notifier::GetInstance().SetOnStart(onStart);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetListenerOnExit(std::function<void()> onExit) {
|
|
|
|
|
Notifier::GetInstance().SetOnExit(onExit);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 12:46:22 -07:00
|
|
|
CS_Listener AddListener(std::function<void(const RawEvent& event)> callback,
|
|
|
|
|
int eventMask, bool immediateNotify,
|
|
|
|
|
CS_Status* status) {
|
2016-11-05 13:13:09 -07:00
|
|
|
int uid = Notifier::GetInstance().AddListener(callback, eventMask);
|
|
|
|
|
if (immediateNotify) {
|
|
|
|
|
// TODO
|
|
|
|
|
}
|
|
|
|
|
return Handle{uid, Handle::kListener};
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
|
|
|
|
|
2016-11-04 12:46:22 -07:00
|
|
|
void RemoveListener(CS_Listener handle, CS_Status* status) {
|
2016-11-05 13:13:09 -07:00
|
|
|
int uid = Handle{handle}.GetTypedIndex(Handle::kListener);
|
|
|
|
|
if (uid < 0) {
|
|
|
|
|
*status = CS_INVALID_HANDLE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Notifier::GetInstance().RemoveListener(uid);
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
2016-11-05 13:13:09 -07:00
|
|
|
bool NotifierDestroyed() { return Notifier::destroyed(); }
|
|
|
|
|
|
2016-08-25 23:13:48 -07:00
|
|
|
//
|
|
|
|
|
// Utility Functions
|
|
|
|
|
//
|
|
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::ArrayRef<CS_Source> EnumerateSourceHandles(
|
|
|
|
|
llvm::SmallVectorImpl<CS_Source>& vec, CS_Status* status) {
|
|
|
|
|
return Sources::GetInstance().GetAll(vec);
|
2016-08-19 23:05:28 -07:00
|
|
|
}
|
2016-08-25 23:13:48 -07:00
|
|
|
|
2016-09-10 21:30:39 -07:00
|
|
|
llvm::ArrayRef<CS_Sink> EnumerateSinkHandles(
|
|
|
|
|
llvm::SmallVectorImpl<CS_Sink>& vec, CS_Status* status) {
|
|
|
|
|
return Sinks::GetInstance().GetAll(vec);
|
2016-08-25 23:13:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace cs
|