diff --git a/cscore/src/main/java/edu/wpi/cscore/CameraServerJNI.java b/cscore/src/main/java/edu/wpi/cscore/CameraServerJNI.java index ac18408fa2..b8a548ca73 100644 --- a/cscore/src/main/java/edu/wpi/cscore/CameraServerJNI.java +++ b/cscore/src/main/java/edu/wpi/cscore/CameraServerJNI.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. 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. */ @@ -120,6 +120,7 @@ public class CameraServerJNI { // // UsbCamera Source Functions // + public static native void setUsbCameraPath(int source, String path); public static native String getUsbCameraPath(int source); public static native UsbCameraInfo getUsbCameraInfo(int source); diff --git a/cscore/src/main/java/edu/wpi/cscore/UsbCamera.java b/cscore/src/main/java/edu/wpi/cscore/UsbCamera.java index fc80047eec..7526335842 100644 --- a/cscore/src/main/java/edu/wpi/cscore/UsbCamera.java +++ b/cscore/src/main/java/edu/wpi/cscore/UsbCamera.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. 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. */ @@ -40,6 +40,13 @@ public class UsbCamera extends VideoCamera { return CameraServerJNI.enumerateUsbCameras(); } + /** + * Change the path to the device. + */ + void setPath(String path) { + CameraServerJNI.setUsbCameraPath(m_handle, path); + } + /** * Get the path to the device. */ diff --git a/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp b/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp index 2b3fb081fd..41906a794c 100644 --- a/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp +++ b/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. 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. */ @@ -44,6 +44,11 @@ CS_Source CS_CreateUsbCameraPath(const char* name, const char* path, return cs::CreateUsbCameraPath(name, path, status); } +void CS_SetUsbCameraPath(CS_Source source, const char* path, + CS_Status* status) { + cs::SetUsbCameraPath(source, path, status); +} + char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status) { return ConvertToC(cs::GetUsbCameraPath(source, status)); } diff --git a/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp b/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp index 52a0fea718..e9408fd920 100644 --- a/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp +++ b/cscore/src/main/native/cpp/jni/CameraServerJNI.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. 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. */ @@ -1026,6 +1026,20 @@ Java_edu_wpi_cscore_CameraServerJNI_setCameraExposureManual CheckStatus(env, status); } +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setUsbCameraPath + * Signature: (ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_cscore_CameraServerJNI_setUsbCameraPath + (JNIEnv* env, jclass, jint source, jstring path) +{ + CS_Status status = 0; + cs::SetUsbCameraPath(source, JStringRef{env, path}.str(), &status); + CheckStatus(env, status); +} + /* * Class: edu_wpi_cscore_CameraServerJNI * Method: getUsbCameraPath diff --git a/cscore/src/main/native/include/cscore_c.h b/cscore/src/main/native/include/cscore_c.h index 24e30b48af..728028cb92 100644 --- a/cscore/src/main/native/include/cscore_c.h +++ b/cscore/src/main/native/include/cscore_c.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. 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. */ @@ -338,6 +338,7 @@ void CS_SetCameraExposureManual(CS_Source source, int value, CS_Status* status); * @defgroup cscore_usbcamera_cfunc UsbCamera Source Functions * @{ */ +void CS_SetUsbCameraPath(CS_Source source, const char* path, CS_Status* status); char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status); CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status); /** @} */ diff --git a/cscore/src/main/native/include/cscore_cpp.h b/cscore/src/main/native/include/cscore_cpp.h index c1ec024ed6..1ee1615ed7 100644 --- a/cscore/src/main/native/include/cscore_cpp.h +++ b/cscore/src/main/native/include/cscore_cpp.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2015-2020 FIRST. 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. */ @@ -274,6 +274,7 @@ void SetCameraExposureManual(CS_Source source, int value, CS_Status* status); * @defgroup cscore_usbcamera_func UsbCamera Source Functions * @{ */ +void SetUsbCameraPath(CS_Source, const wpi::Twine& path, CS_Status* status); std::string GetUsbCameraPath(CS_Source source, CS_Status* status); UsbCameraInfo GetUsbCameraInfo(CS_Source source, CS_Status* status); /** @} */ diff --git a/cscore/src/main/native/include/cscore_oo.h b/cscore/src/main/native/include/cscore_oo.h index 5ab0f70fb0..9e6e29084d 100644 --- a/cscore/src/main/native/include/cscore_oo.h +++ b/cscore/src/main/native/include/cscore_oo.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2015-2020 FIRST. 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. */ @@ -444,6 +444,11 @@ class UsbCamera : public VideoCamera { */ static std::vector EnumerateUsbCameras(); + /** + * Change the path to the device. + */ + void SetPath(const wpi::Twine& path); + /** * Get the path to the device. */ diff --git a/cscore/src/main/native/include/cscore_oo.inl b/cscore/src/main/native/include/cscore_oo.inl index 9a91b0cceb..2d56e1c377 100644 --- a/cscore/src/main/native/include/cscore_oo.inl +++ b/cscore/src/main/native/include/cscore_oo.inl @@ -259,6 +259,11 @@ inline std::vector UsbCamera::EnumerateUsbCameras() { return ::cs::EnumerateUsbCameras(&status); } +inline void UsbCamera::SetPath(const wpi::Twine& path) { + m_status = 0; + return ::cs::SetUsbCameraPath(m_handle, path, &m_status); +} + inline std::string UsbCamera::GetPath() const { m_status = 0; return ::cs::GetUsbCameraPath(m_handle, &m_status); diff --git a/cscore/src/main/native/linux/UsbCameraImpl.cpp b/cscore/src/main/native/linux/UsbCameraImpl.cpp index 453a37243c..1175ca3f42 100644 --- a/cscore/src/main/native/linux/UsbCameraImpl.cpp +++ b/cscore/src/main/native/linux/UsbCameraImpl.cpp @@ -283,10 +283,10 @@ UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier, Telemetry& telemetry, const wpi::Twine& path) : SourceImpl{name, logger, notifier, telemetry}, - m_path{path.str()}, m_fd{-1}, m_command_fd{eventfd(0, 0)}, - m_active{true} { + m_active{true}, + m_path{path.str()} { SetDescription(GetDescriptionImpl(m_path.c_str())); SetQuirks(); @@ -784,6 +784,22 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty( return CS_OK; } +CS_StatusValue UsbCameraImpl::DeviceCmdSetPath( + std::unique_lock& lock, const Message& msg) { + m_path = msg.dataStr; + lock.unlock(); + // disconnect and reconnect + bool wasStreaming = m_streaming; + if (wasStreaming) DeviceStreamOff(); + if (m_fd >= 0) { + DeviceDisconnect(); + DeviceConnect(); + } + if (wasStreaming) DeviceStreamOn(); + lock.lock(); + return CS_OK; +} + CS_StatusValue UsbCameraImpl::DeviceProcessCommand( std::unique_lock& lock, const Message& msg) { if (msg.kind == Message::kCmdSetMode || @@ -797,6 +813,8 @@ CS_StatusValue UsbCameraImpl::DeviceProcessCommand( } else if (msg.kind == Message::kNumSinksChanged || msg.kind == Message::kNumSinksEnabledChanged) { return CS_OK; + } else if (msg.kind == Message::kCmdSetPath) { + return DeviceCmdSetPath(lock, msg); } else { return CS_OK; } @@ -1377,6 +1395,17 @@ void UsbCameraImpl::NumSinksEnabledChanged() { Send(Message{Message::kNumSinksEnabledChanged}); } +void UsbCameraImpl::SetPath(const wpi::Twine& path, CS_Status* status) { + Message msg{Message::kCmdSetPath}; + msg.dataStr = path.str(); + *status = SendAndWait(std::move(msg)); +} + +std::string UsbCameraImpl::GetPath() const { + std::scoped_lock lock(m_mutex); + return m_path; +} + namespace cs { CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev, @@ -1395,6 +1424,16 @@ CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path, inst.telemetry, path)); } +void SetUsbCameraPath(CS_Source source, const wpi::Twine& path, + CS_Status* status) { + auto data = Instance::GetInstance().GetSource(source); + if (!data || data->kind != CS_SOURCE_USB) { + *status = CS_INVALID_HANDLE; + return; + } + static_cast(*data->source).SetPath(path, status); +} + std::string GetUsbCameraPath(CS_Source source, CS_Status* status) { auto data = Instance::GetInstance().GetSource(source); if (!data || data->kind != CS_SOURCE_USB) { diff --git a/cscore/src/main/native/linux/UsbCameraImpl.h b/cscore/src/main/native/linux/UsbCameraImpl.h index 52aaef22d0..62b94a0929 100644 --- a/cscore/src/main/native/linux/UsbCameraImpl.h +++ b/cscore/src/main/native/linux/UsbCameraImpl.h @@ -66,12 +66,14 @@ class UsbCameraImpl : public SourceImpl { void NumSinksChanged() override; void NumSinksEnabledChanged() override; - std::string GetPath() { return m_path; } + void SetPath(const wpi::Twine& path, CS_Status* status); + std::string GetPath() const; // Messages passed to/from camera thread struct Message { enum Kind { kNone = 0, + kCmdSetPath, kCmdSetMode, kCmdSetPixelFormat, kCmdSetResolution, @@ -132,6 +134,8 @@ class UsbCameraImpl : public SourceImpl { const Message& msg); CS_StatusValue DeviceCmdSetProperty(std::unique_lock& lock, const Message& msg); + CS_StatusValue DeviceCmdSetPath(std::unique_lock& lock, + const Message& msg); // Property helper functions int RawToPercentage(const UsbCameraProperty& rawProp, int rawValue); @@ -152,11 +156,6 @@ class UsbCameraImpl : public SourceImpl { static constexpr int kNumBuffers = 4; std::array m_buffers; - // - // Path never changes, so not protected by mutex. - // - std::string m_path; - std::atomic_int m_fd; std::atomic_int m_command_fd; // for command eventfd @@ -176,6 +175,9 @@ class UsbCameraImpl : public SourceImpl { mutable std::vector m_commands; mutable std::vector> m_responses; mutable wpi::condition_variable m_responseCv; + + // Path + std::string m_path; }; } // namespace cs diff --git a/cscore/src/main/native/osx/UsbCameraImpl.cpp b/cscore/src/main/native/osx/UsbCameraImpl.cpp index a10fae4b6b..abefcc7c14 100644 --- a/cscore/src/main/native/osx/UsbCameraImpl.cpp +++ b/cscore/src/main/native/osx/UsbCameraImpl.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. 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. */ @@ -21,6 +21,11 @@ CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path, return 0; } +void SetUsbCameraPath(CS_Source source, const wpi::Twine& path, + CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + std::string GetUsbCameraPath(CS_Source source, CS_Status* status) { *status = CS_INVALID_HANDLE; return std::string{}; diff --git a/cscore/src/main/native/windows/UsbCameraImpl.cpp b/cscore/src/main/native/windows/UsbCameraImpl.cpp index 69c1fcb2e3..7d888c6c55 100644 --- a/cscore/src/main/native/windows/UsbCameraImpl.cpp +++ b/cscore/src/main/native/windows/UsbCameraImpl.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018-2020 FIRST. 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. */ @@ -198,6 +198,20 @@ void UsbCameraImpl::NumSinksEnabledChanged() { SetCameraMessage, Message::kNumSinksEnabledChanged, nullptr); } +void UsbCameraImpl::SetPath(const wpi::Twine& path, CS_Status* status) { + Message msg{Message::kCmdSetPath}; + msg.dataStr = path.str(); + auto result = + m_messagePump->SendWindowMessage( + SetCameraMessage, msg.kind, &msg); + *status = result; +} + +std::string UsbCameraImpl::GetPath() const { + std::scoped_lock lock(m_mutex); + return m_path; +} + void UsbCameraImpl::StartMessagePump() { m_messagePump = std::make_unique( [this](HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) { @@ -705,6 +719,16 @@ CS_StatusValue UsbCameraImpl::DeviceProcessCommand( DeviceStreamOn(); } return CS_OK; + } else if (msgKind == Message::kCmdSetPath) { + { + std::scoped_lock lock(m_mutex); + m_path = msg->dataStr; + std::wstring_convert> utf8_conv; + m_widePath = utf8_conv.from_bytes(m_path.c_str()); + } + DeviceDisconnect(); + DeviceConnect(); + return CS_OK; } else { return CS_OK; } @@ -1052,6 +1076,16 @@ CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path, return inst.CreateSource(CS_SOURCE_USB, source); } +void SetUsbCameraPath(CS_Source source, const wpi::Twine& path, + CS_Status* status) { + auto data = Instance::GetInstance().GetSource(source); + if (!data || data->kind != CS_SOURCE_USB) { + *status = CS_INVALID_HANDLE; + return; + } + static_cast(*data->source).SetPath(path, status); +} + std::string GetUsbCameraPath(CS_Source source, CS_Status* status) { auto data = Instance::GetInstance().GetSource(source); if (!data || data->kind != CS_SOURCE_USB) { diff --git a/cscore/src/main/native/windows/UsbCameraImpl.h b/cscore/src/main/native/windows/UsbCameraImpl.h index 11e07aaf0d..f43e03f464 100644 --- a/cscore/src/main/native/windows/UsbCameraImpl.h +++ b/cscore/src/main/native/windows/UsbCameraImpl.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018-2020 FIRST. 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. */ @@ -78,12 +78,14 @@ class UsbCameraImpl : public SourceImpl, void ProcessFrame(IMFSample* sample, const VideoMode& mode); void PostRequestNewFrame(); - std::string GetPath() { return m_path; } + void SetPath(const wpi::Twine& path, CS_Status* status); + std::string GetPath() const; // Messages passed to/from camera thread struct Message { enum Kind { kNone = 0, + kCmdSetPath, kCmdSetMode, kCmdSetPixelFormat, kCmdSetResolution, @@ -171,9 +173,6 @@ class UsbCameraImpl : public SourceImpl, std::unique_ptr m_messagePump; ComPtr m_currentMode; - // - // Path never changes, so not protected by mutex. - // std::string m_path; std::wstring m_widePath;