diff --git a/include/cameraserver_c.h b/include/cameraserver_c.h index c82ea8b953..d01e8f21bd 100644 --- a/include/cameraserver_c.h +++ b/include/cameraserver_c.h @@ -75,9 +75,8 @@ typedef struct CS_VideoMode { } CS_VideoMode; // -// Property Functions +// Property types // - enum CS_PropertyType { CS_PROP_NONE = 0, CS_PROP_BOOLEAN = 1, @@ -86,6 +85,51 @@ enum CS_PropertyType { CS_PROP_ENUM = 8 }; +// +// Listener event types +// +enum CS_EventType { + CS_SOURCE_CREATED = 0x0001, + CS_SOURCE_DESTROYED = 0x0002, + CS_SOURCE_CONNECTED = 0x0004, + CS_SOURCE_DISCONNECTED = 0x0008, + CS_SOURCE_VIDEOMODES_UPDATED = 0x0010, + CS_SOURCE_VIDEOMODE_CHANGED = 0x0020, + CS_SINK_CREATED = 0x0100, + CS_SINK_DESTROYED = 0x0200, + CS_SINK_ENABLED = 0x0400, + CS_SINK_DISABLED = 0x0800, + CS_SOURCE_PROPERTY_CREATED = 0x1000, + CS_SOURCE_PROPERTY_VALUE_UPDATED = 0x2000, + CS_SOURCE_PROPERTY_CHOICES_UPDATED = 0x4000 +}; + +// +// Listener event +// +struct CS_Event { + CS_EventType type; + + // Valid for CS_SOURCE_* and CS_SINK_* respectively + CS_Source source; + CS_Sink sink; + + // Source/sink name + const char *name; + + // Fields for CS_SOURCE_VIDEOMODE_CHANGED event + CS_VideoMode mode; + + // Fields for CS_SOURCE_PROPERTY_* events + CS_Property property; + CS_PropertyType propertyType; + int value; + const char* valueStr; +}; + +// +// Property Functions +// enum CS_PropertyType CS_GetPropertyType(CS_Property property, CS_Status* status); char* CS_GetPropertyName(CS_Property property, CS_Status* status); @@ -156,10 +200,6 @@ CS_Property CS_CreateSourceProperty(CS_Source source, const char* name, enum CS_PropertyType type, int minimum, int maximum, int step, int defaultValue, int value, CS_Status* status); -CS_Property CS_CreateSourcePropertyCallback( - CS_Source source, const char* name, enum CS_PropertyType type, int minimum, - int maximum, int step, int defaultValue, int value, void* data, - void (*onChange)(void* data, CS_Property property), CS_Status* status); void CS_SetSourceEnumPropertyChoices(CS_Source source, CS_Property property, const char** choices, int count, CS_Status* status); @@ -198,33 +238,12 @@ void CS_SetSinkEnabled(CS_Sink sink, CS_Bool enabled, CS_Status* status); // // Listener Functions // -enum CS_SourceEvent { - CS_SOURCE_CREATED = 0x01, - CS_SOURCE_DESTROYED = 0x02, - CS_SOURCE_CONNECTED = 0x04, - CS_SOURCE_DISCONNECTED = 0x08 -}; +CS_Listener CS_AddListener(void* data, + void (*callback)(void* data, const CS_Event* event), + int eventMask, int immediateNotify, + CS_Status* status); -CS_Listener CS_AddSourceListener(void* data, - void (*callback)(void* data, const char* name, - CS_Source source, int event), - int eventMask, CS_Status* status); - -void CS_RemoveSourceListener(CS_Listener handle, CS_Status* status); - -enum CS_SinkEvent { - CS_SINK_CREATED = 0x01, - CS_SINK_DESTROYED = 0x02, - CS_SINK_ENABLED = 0x04, - CS_SINK_DISABLED = 0x08 -}; - -CS_Listener CS_AddSinkListener(void* data, - void (*callback)(void* data, const char* name, - CS_Sink sink, int event), - int eventMask, CS_Status* status); - -void CS_RemoveSinkListener(CS_Listener handle, CS_Status* status); +void CS_RemoveListener(CS_Listener handle, CS_Status* status); // // Utility Functions diff --git a/include/cameraserver_cpp.h b/include/cameraserver_cpp.h index 6f75104f17..f3d7ec3e55 100644 --- a/include/cameraserver_cpp.h +++ b/include/cameraserver_cpp.h @@ -65,10 +65,46 @@ struct VideoMode : public CS_VideoMode { explicit operator bool() const { return pixelFormat == kUnknown; } }; +/// Listener event +struct RawEvent { + enum Type { + kSourceCreated = CS_SOURCE_CREATED, + kSourceDestroyed = CS_SOURCE_DESTROYED, + kSourceConnected = CS_SOURCE_CONNECTED, + kSourceDisconnected = CS_SOURCE_DISCONNECTED, + kSourceVideoModesUpdated = CS_SOURCE_VIDEOMODES_UPDATED, + kSourceVideoModeChanged = CS_SOURCE_VIDEOMODE_CHANGED, + kSinkCreated = CS_SINK_CREATED, + kSinkDestroyed = CS_SINK_DESTROYED, + kSinkEnabled = CS_SINK_ENABLED, + kSinkDisabled = CS_SINK_DISABLED, + kSourcePropertyCreated = CS_SOURCE_PROPERTY_CREATED, + kSourcePropertyValueUpdated = CS_SOURCE_PROPERTY_VALUE_UPDATED, + kSourcePropertyChoicesUpdated = CS_SOURCE_PROPERTY_CHOICES_UPDATED + }; + + Type type; + + // Valid for kSource* and kSink* respectively + CS_Source sourceHandle; + CS_Sink sinkHandle; + + // Source/sink name + std::string name; + + // Fields for kSourceVideoModeChanged event + VideoMode mode; + + // Fields for CS_SOURCE_PROPERTY_* events + CS_Property propertyHandle; + CS_PropertyType propertyType; + int value; + std::string valueStr; +}; + // // Property Functions // - CS_PropertyType GetPropertyType(CS_Property property, CS_Status* status); std::string GetPropertyName(CS_Property property, CS_Status* status); llvm::StringRef GetPropertyName(CS_Property property, @@ -144,10 +180,6 @@ CS_Property CreateSourceProperty(CS_Source source, llvm::StringRef name, CS_PropertyType type, int minimum, int maximum, int step, int defaultValue, int value, CS_Status* status); -CS_Property CreateSourcePropertyCallback( - CS_Source source, llvm::StringRef name, CS_PropertyType type, int minimum, - int maximum, int step, int defaultValue, int value, - std::function onChange, CS_Status* status); void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property, llvm::ArrayRef choices, CS_Status* status); @@ -193,18 +225,10 @@ void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status); // // Listener Functions // -CS_Listener AddSourceListener( - std::function - callback, - int eventMask, CS_Status* status); +CS_Listener AddListener(std::function callback, + int eventMask, bool immediateNotify, CS_Status* status); -void RemoveSourceListener(CS_Listener handle, CS_Status* status); - -CS_Listener AddSinkListener( - std::function callback, - int eventMask, CS_Status* status); - -void RemoveSinkListener(CS_Listener handle, CS_Status* status); +void RemoveListener(CS_Listener handle, CS_Status* status); // // Utility Functions diff --git a/include/cameraserver_oo.h b/include/cameraserver_oo.h index 0d3285b881..2fe7d5388e 100644 --- a/include/cameraserver_oo.h +++ b/include/cameraserver_oo.h @@ -18,13 +18,13 @@ namespace cs { // Forward declarations so friend declarations work correctly class CvSource; -class SinkListener; -class SourceListener; +class VideoEvent; class VideoSink; class VideoSource; class VideoProperty { friend class CvSource; + friend class VideoEvent; friend class VideoSink; friend class VideoSource; @@ -70,6 +70,7 @@ class VideoProperty { private: explicit VideoProperty(CS_Property handle); + VideoProperty(CS_Property handle, Type type); mutable CS_Status m_status; CS_Property m_handle; @@ -78,7 +79,7 @@ class VideoProperty { /// A source for video that provides a sequence of frames. class VideoSource { - friend class SourceListener; + friend class VideoEvent; friend class VideoSink; public: @@ -241,21 +242,6 @@ class CvSource : public VideoSource { int minimum, int maximum, int step, int defaultValue, int value); - /// Create a property with a change callback. - /// @param name Property name - /// @param type Property type - /// @param minimum Minimum value - /// @param maximum Maximum value - /// @param step Step value - /// @param defaultValue Default value - /// @param value Current value - /// @param onChange Callback to call when the property value changes - /// @return Property - VideoProperty CreateProperty( - llvm::StringRef name, VideoProperty::Type type, int minimum, int maximum, - int step, int defaultValue, int value, - std::function onChange); - /// Configure enum property choices. /// @param property Property /// @param choices Choices @@ -265,7 +251,7 @@ class CvSource : public VideoSource { /// A sink for video that accepts a sequence of frames. class VideoSink { - friend class SinkListener; + friend class VideoEvent; public: VideoSink() noexcept : m_handle(0) {} @@ -372,56 +358,25 @@ class CvSink : public VideoSink { void SetEnabled(bool enabled); }; -class SourceListener { +class VideoEvent : public RawEvent { public: - enum Event { - kCreated = CS_SOURCE_CREATED, - kDestroyed = CS_SOURCE_DESTROYED, - kConnected = CS_SOURCE_CONNECTED, - kDisconnected = CS_SOURCE_DISCONNECTED - }; - - SourceListener() : m_handle(0) {} - SourceListener( - std::function - callback, - int eventMask); - - SourceListener(const SourceListener&) = delete; - SourceListener& operator=(const SourceListener&) = delete; - SourceListener(SourceListener&& other) noexcept; - ~SourceListener(); - - friend void swap(SourceListener& first, SourceListener& second) noexcept { - using std::swap; - swap(first.m_handle, second.m_handle); - } - - private: - CS_Listener m_handle; + VideoSource GetSource() const; + VideoSink GetSink() const; + VideoProperty GetProperty() const; }; -class SinkListener { +class VideoListener { public: - enum Event { - kCreated = CS_SINK_CREATED, - kDestroyed = CS_SINK_DESTROYED, - kEnabled = CS_SINK_ENABLED, - kDisabled = CS_SINK_DISABLED - }; + VideoListener() : m_handle(0) {} + VideoListener(std::function callback, + int eventMask, bool immediateNotify); - SinkListener() : m_handle(0) {} - SinkListener( - std::function - callback, - int eventMask); + VideoListener(const VideoListener&) = delete; + VideoListener& operator=(const VideoListener&) = delete; + VideoListener(VideoListener&& other) noexcept; + ~VideoListener(); - SinkListener(const SinkListener&) = delete; - SinkListener& operator=(const SinkListener&) = delete; - SinkListener(SinkListener&& other) noexcept; - ~SinkListener(); - - friend void swap(SinkListener& first, SinkListener& second) noexcept { + friend void swap(VideoListener& first, VideoListener& second) noexcept { using std::swap; swap(first.m_handle, second.m_handle); } diff --git a/include/cameraserver_oo.inl b/include/cameraserver_oo.inl index dd4998762f..d0abc275ab 100644 --- a/include/cameraserver_oo.inl +++ b/include/cameraserver_oo.inl @@ -213,18 +213,6 @@ inline VideoProperty CvSource::CreateProperty(llvm::StringRef name, minimum, maximum, step, defaultValue, value, &m_status)}; } -inline VideoProperty CvSource::CreateProperty( - llvm::StringRef name, VideoProperty::Type type, int minimum, int maximum, - int step, int defaultValue, int value, - std::function onChange) { - m_status = 0; - return VideoProperty{CreateSourcePropertyCallback( - m_handle, name, static_cast(static_cast(type)), - minimum, maximum, step, defaultValue, value, - [=](CS_Property property) { onChange(VideoProperty{property}); }, - &m_status)}; -} - inline void CvSource::SetEnumPropertyChoices( const VideoProperty& property, llvm::ArrayRef choices) { m_status = 0; @@ -310,48 +298,40 @@ inline void CvSink::SetEnabled(bool enabled) { SetSinkEnabled(m_handle, enabled, &m_status); } -inline SourceListener::SourceListener( - std::function - callback, - int eventMask) { +inline VideoSource VideoEvent::GetSource() const { CS_Status status = 0; - m_handle = AddSourceListener( - [=](llvm::StringRef name, CS_Source sourceHandle, int event) { - callback(name, VideoSource{sourceHandle}, event); - }, - eventMask, &status); + return VideoSource{sourceHandle == 0 ? 0 : CopySource(sourceHandle, &status)}; } -inline SourceListener::SourceListener(SourceListener&& other) noexcept - : SourceListener() { +inline VideoSink VideoEvent::GetSink() const { + CS_Status status = 0; + return VideoSink{sinkHandle == 0 ? 0 : CopySink(sinkHandle, &status)}; +} + +inline VideoProperty VideoEvent::GetProperty() const { + return VideoProperty{propertyHandle, + static_cast(propertyType)}; +} + +inline VideoListener::VideoListener( + std::function callback, int eventMask, + bool immediateNotify) { + CS_Status status = 0; + m_handle = AddListener( + [=](const RawEvent& event) { + callback(static_cast(event)); + }, + eventMask, immediateNotify, &status); +} + +inline VideoListener::VideoListener(VideoListener&& other) noexcept + : VideoListener() { swap(*this, other); } -inline SourceListener::~SourceListener() { +inline VideoListener::~VideoListener() { CS_Status status = 0; - if (m_handle != 0) RemoveSourceListener(m_handle, &status); -} - -inline SinkListener::SinkListener( - std::function - callback, - int eventMask) { - CS_Status status = 0; - m_handle = AddSinkListener( - [=](llvm::StringRef name, CS_Sink sinkHandle, int event) { - callback(name, VideoSink{sinkHandle}, event); - }, - eventMask, &status); -} - -inline SinkListener::SinkListener(SinkListener&& other) noexcept - : SinkListener() { - swap(*this, other); -} - -inline SinkListener::~SinkListener() { - CS_Status status = 0; - if (m_handle != 0) RemoveSinkListener(m_handle, &status); + if (m_handle != 0) RemoveListener(m_handle, &status); } } // namespace cs diff --git a/java/lib/CameraServerJNI.cpp b/java/lib/CameraServerJNI.cpp index ca002e21bd..3e9ab2a7c7 100644 --- a/java/lib/CameraServerJNI.cpp +++ b/java/lib/CameraServerJNI.cpp @@ -800,27 +800,14 @@ JNIEXPORT void JNICALL Java_edu_wpi_cameraserver_CameraServerJNI_setSinkEnabled /* * Class: edu_wpi_cameraserver_CameraServerJNI - * Method: removeSourceListener + * Method: removeListener * Signature: (I)V */ -JNIEXPORT void JNICALL Java_edu_wpi_cameraserver_CameraServerJNI_removeSourceListener +JNIEXPORT void JNICALL Java_edu_wpi_cameraserver_CameraServerJNI_removeListener (JNIEnv *env, jclass, jint handle) { CS_Status status = 0; - cs::RemoveSourceListener(handle, &status); - CheckStatus(env, status); -} - -/* - * Class: edu_wpi_cameraserver_CameraServerJNI - * Method: removeSinkListener - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_edu_wpi_cameraserver_CameraServerJNI_removeSinkListener - (JNIEnv *env, jclass, jint handle) -{ - CS_Status status = 0; - cs::RemoveSinkListener(handle, &status); + cs::RemoveListener(handle, &status); CheckStatus(env, status); } diff --git a/java/src/edu/wpi/cameraserver/CameraServerJNI.java b/java/src/edu/wpi/cameraserver/CameraServerJNI.java index 4f69493ad7..ef4f4f7539 100644 --- a/java/src/edu/wpi/cameraserver/CameraServerJNI.java +++ b/java/src/edu/wpi/cameraserver/CameraServerJNI.java @@ -156,16 +156,10 @@ public class CameraServerJNI { // // Listener Functions // - //public static native int addSourceListener(void (*callback)(String name, int source, - // int event), + //public static native int addListener(void (*callback)(VideoEvent event), // int eventMask); - public static native void removeSourceListener(int handle); - - //public static native int addSinkListener(void (*callback)(String name, int sink, int event), - // int eventMask); - - public static native void removeSinkListener(int handle); + public static native void removeListener(int handle); // // Utility Functions diff --git a/src/cameraserver_c.cpp b/src/cameraserver_c.cpp index 69f8d28af3..5a421cd619 100644 --- a/src/cameraserver_c.cpp +++ b/src/cameraserver_c.cpp @@ -211,46 +211,29 @@ void CS_ReleaseSink(CS_Sink sink, CS_Status* status) { return cs::ReleaseSink(sink, status); } -CS_Listener CS_AddSourceListener(void* data, - void (*callback)(void* data, const char* name, - CS_Source source, int event), - int eventMask, CS_Status* status) { - return cs::AddSourceListener( - [=](llvm::StringRef name, CS_Source source, int event) { - // avoid the copy if possible - if (name[name.size()] == '\0') { - callback(data, name.data(), source, event); - } else { - llvm::SmallString<128> copy{name}; - callback(data, copy.c_str(), source, event); - } +CS_Listener CS_AddListener(void* data, + void (*callback)(void* data, const CS_Event* event), + int eventMask, int immediateNotify, + CS_Status* status) { + return cs::AddListener( + [=](const cs::RawEvent& rawEvent) { + CS_Event event; + event.type = static_cast(static_cast(rawEvent.type)); + event.source = rawEvent.sourceHandle; + event.sink = rawEvent.sinkHandle; + event.name = rawEvent.name.c_str(); + event.mode = rawEvent.mode; + event.property = rawEvent.propertyHandle; + event.propertyType = rawEvent.propertyType; + event.value = rawEvent.value; + event.valueStr = rawEvent.valueStr.c_str(); + callback(data, &event); }, - eventMask, status); + eventMask, immediateNotify, status); } -void CS_RemoveSourceListener(CS_Listener handle, CS_Status* status) { - return cs::RemoveSourceListener(handle, status); -} - -CS_Listener CS_AddSinkListener(void* data, - void (*callback)(void* data, const char* name, - CS_Sink sink, int event), - int eventMask, CS_Status* status) { - return cs::AddSinkListener( - [=](llvm::StringRef name, CS_Sink sink, int event) { - // avoid the copy if possible - if (name[name.size()] == '\0') { - callback(data, name.data(), sink, event); - } else { - llvm::SmallString<128> copy{name}; - callback(data, copy.c_str(), sink, event); - } - }, - eventMask, status); -} - -void CS_RemoveSinkListener(CS_Listener handle, CS_Status* status) { - return cs::RemoveSinkListener(handle, status); +void CS_RemoveListener(CS_Listener handle, CS_Status* status) { + return cs::RemoveListener(handle, status); } CS_Source* CS_EnumerateSources(int* count, CS_Status* status) { diff --git a/src/cameraserver_cpp.cpp b/src/cameraserver_cpp.cpp index f58c195565..70a9869be9 100644 --- a/src/cameraserver_cpp.cpp +++ b/src/cameraserver_cpp.cpp @@ -424,24 +424,13 @@ void ReleaseSink(CS_Sink sink, CS_Status* status) { // Listener Functions // -CS_Listener AddSourceListener( - std::function - callback, - int eventMask, CS_Status* status) { +CS_Listener AddListener(std::function callback, + int eventMask, bool immediateNotify, + CS_Status* status) { return 0; // TODO } -void RemoveSourceListener(CS_Listener handle, CS_Status* status) { - // TODO -} - -CS_Listener AddSinkListener( - std::function callback, - int eventMask, CS_Status* status) { - return 0; // TODO -} - -void RemoveSinkListener(CS_Listener handle, CS_Status* status) { +void RemoveListener(CS_Listener handle, CS_Status* status) { // TODO }