diff --git a/include/cscore_c.h b/include/cscore_c.h index 4ba849774c..9cd431a869 100644 --- a/include/cscore_c.h +++ b/include/cscore_c.h @@ -210,6 +210,11 @@ CS_Sink* CS_EnumerateSourceSinks(CS_Source source, int* count, CS_Source CS_CopySource(CS_Source source, CS_Status* status); void CS_ReleaseSource(CS_Source source, CS_Status* status); +// +// USBCamera Source Functions +// +char* CS_GetUSBCameraPath(CS_Source source, CS_Status* status); + // // OpenCV Source Functions // @@ -251,6 +256,12 @@ CS_Source CS_GetSinkSource(CS_Sink sink, CS_Status* status); CS_Sink CS_CopySink(CS_Sink sink, CS_Status* status); void CS_ReleaseSink(CS_Sink sink, CS_Status* status); +// +// MJPEGServer Sink Functions +// +char* CS_GetMJPEGServerListenAddress(CS_Sink sink, CS_Status* status); +int CS_GetMJPEGServerPort(CS_Sink sink, CS_Status* status); + // // OpenCV Sink Functions // diff --git a/include/cscore_cpp.h b/include/cscore_cpp.h index d4a5abf80c..0509bbe522 100644 --- a/include/cscore_cpp.h +++ b/include/cscore_cpp.h @@ -198,6 +198,11 @@ llvm::ArrayRef EnumerateSourceSinks( CS_Source CopySource(CS_Source source, CS_Status* status); void ReleaseSource(CS_Source source, CS_Status* status); +// +// USBCamera Source Functions +// +std::string GetUSBCameraPath(CS_Source source, CS_Status* status); + // // OpenCV Source Functions // @@ -243,6 +248,12 @@ CS_Source GetSinkSource(CS_Sink sink, CS_Status* status); CS_Sink CopySink(CS_Sink sink, CS_Status* status); void ReleaseSink(CS_Sink sink, CS_Status* status); +// +// MJPEGServer Sink Functions +// +std::string GetMJPEGServerListenAddress(CS_Sink sink, CS_Status* status); +int GetMJPEGServerPort(CS_Sink sink, CS_Status* status); + // // OpenCV Sink Functions // diff --git a/include/cscore_oo.h b/include/cscore_oo.h index 19bd86f7cc..b78c1efdf4 100644 --- a/include/cscore_oo.h +++ b/include/cscore_oo.h @@ -223,6 +223,9 @@ class USBCamera : public VideoSource { /// @return Vector of USB camera information (one for each camera) static std::vector EnumerateUSBCameras(); + /// Get the path to the device. + std::string GetPath() const; + /// Set the brightness, as a percentage (0-100). void SetBrightness(int brightness); @@ -402,6 +405,12 @@ class MJPEGServer : public VideoSink { /// @param name Sink name (arbitrary unique identifier) /// @param port TCP port number MJPEGServer(llvm::StringRef name, int port) : MJPEGServer(name, "", port) {} + + /// Get the listen address of the server. + std::string GetListenAddress() const; + + /// Get the port number of the server. + int GetPort() const; }; /// A sink for user code to accept video frames as OpenCV images. diff --git a/include/cscore_oo.inl b/include/cscore_oo.inl index a9fc7516a5..f73d02bdcc 100644 --- a/include/cscore_oo.inl +++ b/include/cscore_oo.inl @@ -173,6 +173,11 @@ inline std::vector USBCamera::EnumerateUSBCameras() { return ::cs::EnumerateUSBCameras(&status); } +inline std::string USBCamera::GetPath() const { + CS_Status status = 0; + return ::cs::GetUSBCameraPath(m_handle, &status); +} + inline void USBCamera::SetBrightness(int brightness) { if (brightness > 100) { brightness = 100; @@ -323,6 +328,16 @@ inline MJPEGServer::MJPEGServer(llvm::StringRef name, m_handle = CreateMJPEGServer(name, listenAddress, port, &m_status); } +inline std::string MJPEGServer::GetListenAddress() const { + m_status = 0; + return cs::GetMJPEGServerListenAddress(m_handle, &m_status); +} + +inline int MJPEGServer::GetPort() const { + m_status = 0; + return cs::GetMJPEGServerPort(m_handle, &m_status); +} + inline CvSink::CvSink(llvm::StringRef name) { m_handle = CreateCvSink(name, &m_status); } diff --git a/java/src/edu/wpi/cscore/CameraServerJNI.java b/java/src/edu/wpi/cscore/CameraServerJNI.java index 64f5c369d7..df0c4de183 100644 --- a/java/src/edu/wpi/cscore/CameraServerJNI.java +++ b/java/src/edu/wpi/cscore/CameraServerJNI.java @@ -127,6 +127,11 @@ public class CameraServerJNI { public static native int copySource(int source); public static native void releaseSource(int source); + // + // USBCamera Source Functions + // + public static native String getUSBCameraPath(int source); + // // OpenCV Source Functions // @@ -157,6 +162,12 @@ public class CameraServerJNI { public static native int copySink(int sink); public static native void releaseSink(int sink); + // + // MJPEGServer Sink Functions + // + public static native String getMJPEGServerListenAddress(int sink); + public static native int getMJPEGServerPort(int sink); + // // OpenCV Sink Functions // diff --git a/java/src/edu/wpi/cscore/MJPEGServer.java b/java/src/edu/wpi/cscore/MJPEGServer.java index b161c95c7a..db7a4deef3 100644 --- a/java/src/edu/wpi/cscore/MJPEGServer.java +++ b/java/src/edu/wpi/cscore/MJPEGServer.java @@ -23,4 +23,14 @@ public class MJPEGServer extends VideoSink { public MJPEGServer(String name, int port) { this(name, "", port); } + + /// Get the listen address of the server. + public String getListenAddress() { + return CameraServerJNI.getMJPEGServerListenAddress(m_handle); + } + + /// Get the port number of the server. + public int getPort() { + return CameraServerJNI.getMJPEGServerPort(m_handle); + } } diff --git a/java/src/edu/wpi/cscore/USBCamera.java b/java/src/edu/wpi/cscore/USBCamera.java index 3bcad348c8..94e7e48fcb 100644 --- a/java/src/edu/wpi/cscore/USBCamera.java +++ b/java/src/edu/wpi/cscore/USBCamera.java @@ -50,6 +50,11 @@ public class USBCamera extends VideoSource { return CameraServerJNI.enumerateUSBCameras(); } + /// Get the path to the device. + public String getPath() { + return CameraServerJNI.getUSBCameraPath(m_handle); + } + /// Set the brightness, as a percentage (0-100). public synchronized void setBrightness(int brightness) { if (brightness > 100) { diff --git a/src/MJPEGServerImpl.cpp b/src/MJPEGServerImpl.cpp index 027413a70d..68d46d5db2 100644 --- a/src/MJPEGServerImpl.cpp +++ b/src/MJPEGServerImpl.cpp @@ -15,6 +15,7 @@ #include "support/raw_socket_ostream.h" #include "tcpsockets/TCPAcceptor.h" +#include "c_util.h" #include "cscore_cpp.h" #include "Handle.h" #include "Log.h" @@ -401,11 +402,19 @@ void MJPEGServerImpl::ConnThread::SendJSON(llvm::raw_ostream& os, } MJPEGServerImpl::MJPEGServerImpl(llvm::StringRef name, - llvm::StringRef description, + llvm::StringRef listenAddress, int port, std::unique_ptr acceptor) - : SinkImpl{name}, m_acceptor{std::move(acceptor)} { + : SinkImpl{name}, + m_listenAddress(listenAddress), + m_port(port), + m_acceptor{std::move(acceptor)} { m_active = true; - SetDescription(description); + + llvm::SmallString<128> descBuf; + llvm::raw_svector_ostream desc{descBuf}; + desc << "HTTP Server on port " << port; + SetDescription(desc.str()); + m_serverThread = std::thread(&MJPEGServerImpl::ServerThreadMain, this); } @@ -689,12 +698,9 @@ namespace cs { CS_Sink CreateMJPEGServer(llvm::StringRef name, llvm::StringRef listenAddress, int port, CS_Status* status) { - llvm::SmallString<128> descBuf; - llvm::raw_svector_ostream desc{descBuf}; - desc << "HTTP Server on port " << port; llvm::SmallString<128> str{listenAddress}; auto sink = std::make_shared( - name, desc.str(), + name, listenAddress, port, std::unique_ptr( new wpi::TCPAcceptor(port, str.c_str(), Logger::GetInstance()))); auto handle = Sinks::GetInstance().Allocate(CS_SINK_MJPEG, sink); @@ -702,6 +708,24 @@ CS_Sink CreateMJPEGServer(llvm::StringRef name, llvm::StringRef listenAddress, return handle; } +std::string GetMJPEGServerListenAddress(CS_Sink sink, CS_Status* status) { + auto data = Sinks::GetInstance().Get(sink); + if (!data || data->kind != CS_SINK_MJPEG) { + *status = CS_INVALID_HANDLE; + return std::string{}; + } + return static_cast(*data->sink).GetListenAddress(); +} + +int GetMJPEGServerPort(CS_Sink sink, CS_Status* status) { + auto data = Sinks::GetInstance().Get(sink); + if (!data || data->kind != CS_SINK_MJPEG) { + *status = CS_INVALID_HANDLE; + return 0; + } + return static_cast(*data->sink).GetPort(); +} + } // namespace cs extern "C" { @@ -711,4 +735,12 @@ CS_Sink CS_CreateMJPEGServer(const char* name, const char* listenAddress, return cs::CreateMJPEGServer(name, listenAddress, port, status); } +char* CS_GetMJPEGServerListenAddress(CS_Sink sink, CS_Status* status) { + return ConvertToC(cs::GetMJPEGServerListenAddress(sink, status)); +} + +int CS_GetMJPEGServerPort(CS_Sink sink, CS_Status* status) { + return cs::GetMJPEGServerPort(sink, status); +} + } // extern "C" diff --git a/src/MJPEGServerImpl.h b/src/MJPEGServerImpl.h index cf288b8899..491fe8d376 100644 --- a/src/MJPEGServerImpl.h +++ b/src/MJPEGServerImpl.h @@ -30,11 +30,13 @@ class SourceImpl; class MJPEGServerImpl : public SinkImpl { public: - MJPEGServerImpl(llvm::StringRef name, llvm::StringRef description, + MJPEGServerImpl(llvm::StringRef name, llvm::StringRef listenAddress, int port, std::unique_ptr acceptor); ~MJPEGServerImpl() override; void Stop(); + std::string GetListenAddress() { return m_listenAddress; } + int GetPort() { return m_port; } private: void SetSourceImpl(std::shared_ptr source) override; @@ -43,6 +45,10 @@ class MJPEGServerImpl : public SinkImpl { class ConnThread; + // Never changed, so not protected by mutex + std::string m_listenAddress; + int m_port; + std::unique_ptr m_acceptor; std::atomic_bool m_active; // set to false to terminate threads std::thread m_serverThread; diff --git a/src/USBCameraImpl.cpp b/src/USBCameraImpl.cpp index 9cbfbee96a..b41ce5fa23 100644 --- a/src/USBCameraImpl.cpp +++ b/src/USBCameraImpl.cpp @@ -1405,6 +1405,15 @@ CS_Source CreateUSBCameraPath(llvm::StringRef name, llvm::StringRef path, return handle; } +std::string GetUSBCameraPath(CS_Source source, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data || data->kind != CS_SOURCE_USB) { + *status = CS_INVALID_HANDLE; + return std::string{}; + } + return static_cast(*data->source).GetPath(); +} + std::vector EnumerateUSBCameras(CS_Status* status) { std::vector retval; @@ -1454,6 +1463,10 @@ CS_Source CS_CreateUSBCameraPath(const char* name, const char* path, return cs::CreateUSBCameraPath(name, path, status); } +char* CS_GetUSBCameraPath(CS_Source source, CS_Status* status) { + return ConvertToC(cs::GetUSBCameraPath(source, status)); +} + CS_USBCameraInfo* CS_EnumerateUSBCameras(int* count, CS_Status* status) { auto cameras = cs::EnumerateUSBCameras(status); CS_USBCameraInfo* out = static_cast( diff --git a/src/USBCameraImpl.h b/src/USBCameraImpl.h index 4f627f1928..a8e1577bd1 100644 --- a/src/USBCameraImpl.h +++ b/src/USBCameraImpl.h @@ -49,6 +49,8 @@ class USBCameraImpl : public SourceImpl { void NumSinksChanged() override; void NumSinksEnabledChanged() override; + std::string GetPath() { return m_path; } + // Property data class PropertyData : public PropertyBase { public: