From d6e2b8a332862d06f548abc649fb037c628a2604 Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Mon, 28 Oct 2019 11:10:44 -0400 Subject: [PATCH] video device: use device id instead of friendly name - Video settings, and APIs will now use a device id, which will be a path on platforms where everything is a file, and a DevicePath with a bonus ffmpeg-dshow compliant prefix on Windows. - The device's friendly name is uniquified, and stored in the settings still, but only retrieved/translated for UI. - MRLs are now constructed with the device id. Change-Id: I092f08cc2cd31bd78aeec5c774c2cc33d75c1d4e --- bin/dbus/cx.ring.Ring.VideoManager.xml | 24 +-- bin/dbus/dbusvideomanager.cpp | 20 +- bin/dbus/dbusvideomanager.h | 10 +- src/client/videomanager.cpp | 30 +-- src/client/videomanager.h | 2 +- src/dring/videomanager_interface.h | 14 +- .../video/androidvideo/video_device_impl.cpp | 1 + .../video/iosvideo/video_device_impl.cpp | 2 +- src/media/video/osxvideo/video_device_impl.mm | 8 +- src/media/video/v4l2/video_device_impl.cpp | 10 +- src/media/video/video_base.cpp | 4 + src/media/video/video_base.h | 1 + src/media/video/video_device.h | 8 +- src/media/video/video_device_monitor.cpp | 176 +++++++----------- src/media/video/video_device_monitor.h | 10 +- .../video/winvideo/video_device_impl.cpp | 16 +- .../winvideo/video_device_monitor_impl.cpp | 6 +- 17 files changed, 155 insertions(+), 187 deletions(-) diff --git a/bin/dbus/cx.ring.Ring.VideoManager.xml b/bin/dbus/cx.ring.Ring.VideoManager.xml index 4b637dc602..6d0d51202b 100644 --- a/bin/dbus/cx.ring.Ring.VideoManager.xml +++ b/bin/dbus/cx.ring.Ring.VideoManager.xml @@ -4,33 +4,33 @@ <!-- Video device methods --> <method name="getDeviceList" tp:name-for-bindings="getDeviceList"> - <tp:docstring>Returns a list of the detected v4l2 devices</tp:docstring> + <tp:docstring>Returns a list of ids for detected devices</tp:docstring> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="as" name="list" direction="out"> </arg> </method> <method name="getCapabilities" tp:name-for-bindings="getCapabilities"> - <tp:docstring>Returns a map of map of array of strings, containing the capabilities (channel, size, rate) of a device</tp:docstring> + <tp:docstring>Returns a map of map of array of strings, containing the capabilities (channel, size, rate) for a given device id</tp:docstring> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringMapStringVectorString"/> - <arg type="s" name="name" direction="in"> + <arg type="s" name="deviceId" direction="in"> </arg> <arg type="a{sa{sas}}" name="cap" direction="out"> </arg> </method> <method name="getSettings" tp:name-for-bindings="getSettings"> - <tp:docstring>Returns a map of settings for the given device name</tp:docstring> + <tp:docstring>Returns a map of settings for the given device id</tp:docstring> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> - <arg type="s" name="device" direction="in"> + <arg type="s" name="deviceId" direction="in"> </arg> <arg type="a{ss}" name="map" direction="out"> </arg> </method> <method name="applySettings" tp:name-for-bindings="applySettings"> - <tp:docstring>Set the preferred settings for a given device name</tp:docstring> - <arg type="s" name="name" direction="in"> + <tp:docstring>Set the preferred settings for a given device id</tp:docstring> + <arg type="s" name="deviceId" direction="in"> </arg> <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="MapStringString"/> <arg type="a{ss}" name="settings" direction="in"> @@ -38,12 +38,14 @@ </method> <method name="getDefaultDevice" tp:name-for-bindings="getDefaultDevice"> - <arg type="s" name="name" direction="out"> + <tp:docstring>Returns the default device id</tp:docstring> + <arg type="s" name="deviceId" direction="out"> </arg> </method> <method name="setDefaultDevice" tp:name-for-bindings="setDefaultDevice"> - <arg type="s" name="name" direction="in"> + <tp:docstring>Sets the default device id</tp:docstring> + <arg type="s" name="deviceId" direction="in"> </arg> </method> @@ -132,8 +134,8 @@ </method> <method name="setDeviceOrientation" tp:name-for-bindings="setDeviceOrientation"> - <arg type="s" name="name" direction="in"> - <tp:docstring>Device name</tp:docstring> + <arg type="s" name="deviceId" direction="in"> + <tp:docstring>Device id</tp:docstring> </arg> <arg type="i" name="angle" direction="in"> <tp:docstring>Angle of device in degrees (counterclockwise)</tp:docstring> diff --git a/bin/dbus/dbusvideomanager.cpp b/bin/dbus/dbusvideomanager.cpp index febe4a0083..cb3cbbe5ef 100644 --- a/bin/dbus/dbusvideomanager.cpp +++ b/bin/dbus/dbusvideomanager.cpp @@ -32,27 +32,27 @@ DBusVideoManager::getDeviceList() -> decltype(DRing::getDeviceList()) } auto -DBusVideoManager::getCapabilities(const std::string& name) -> decltype(DRing::getCapabilities(name)) +DBusVideoManager::getCapabilities(const std::string& deviceId) -> decltype(DRing::getCapabilities(deviceId)) { - return DRing::getCapabilities(name); + return DRing::getCapabilities(deviceId); } auto -DBusVideoManager::getSettings(const std::string& name) -> decltype(DRing::getSettings(name)) +DBusVideoManager::getSettings(const std::string& deviceId) -> decltype(DRing::getSettings(deviceId)) { - return DRing::getSettings(name); + return DRing::getSettings(deviceId); } void -DBusVideoManager::applySettings(const std::string& name, const std::map<std::string, std::string>& settings) +DBusVideoManager::applySettings(const std::string& deviceId, const std::map<std::string, std::string>& settings) { - DRing::applySettings(name, settings); + DRing::applySettings(deviceId, settings); } void -DBusVideoManager::setDefaultDevice(const std::string& dev) +DBusVideoManager::setDefaultDevice(const std::string& deviceId) { - DRing::setDefaultDevice(dev); + DRing::setDefaultDevice(deviceId); } auto @@ -122,9 +122,9 @@ DBusVideoManager::setEncodingAccelerated(const bool& state) } void -DBusVideoManager::setDeviceOrientation(const std::string& name, const int& angle) +DBusVideoManager::setDeviceOrientation(const std::string& deviceId, const int& angle) { - DRing::setDeviceOrientation(name, angle); + DRing::setDeviceOrientation(deviceId, angle); } std::map<std::string, std::string> diff --git a/bin/dbus/dbusvideomanager.h b/bin/dbus/dbusvideomanager.h index 1cd3b7088f..4ed8d8d1ca 100644 --- a/bin/dbus/dbusvideomanager.h +++ b/bin/dbus/dbusvideomanager.h @@ -52,10 +52,10 @@ class DRING_PUBLIC DBusVideoManager : // Methods std::vector<std::string> getDeviceList(); - std::map<std::string, std::map<std::string, std::vector<std::string>>> getCapabilities(const std::string& name); - std::map<std::string, std::string> getSettings(const std::string& name); - void applySettings(const std::string& name, const std::map<std::string, std::string>& settings); - void setDefaultDevice(const std::string& dev); + std::map<std::string, std::map<std::string, std::vector<std::string>>> getCapabilities(const std::string& deviceId); + std::map<std::string, std::string> getSettings(const std::string& deviceId); + void applySettings(const std::string& deviceId, const std::map<std::string, std::string>& settings); + void setDefaultDevice(const std::string& deviceId); std::string getDefaultDevice(); void startCamera(); void stopCamera(); @@ -67,7 +67,7 @@ class DRING_PUBLIC DBusVideoManager : void setDecodingAccelerated(const bool& state); bool getEncodingAccelerated(); void setEncodingAccelerated(const bool& state); - void setDeviceOrientation(const std::string& name, const int& angle); + void setDeviceOrientation(const std::string& deviceId, const int& angle); std::map<std::string, std::string> getRenderer(const std::string& callId); std::string startLocalRecorder(const bool& audioOnly, const std::string& filepath); void stopLocalRecorder(const std::string& filepath); diff --git a/src/client/videomanager.cpp b/src/client/videomanager.cpp index c2c993e501..696c4048ce 100644 --- a/src/client/videomanager.cpp +++ b/src/client/videomanager.cpp @@ -329,9 +329,9 @@ getDeviceList() } VideoCapabilities -getCapabilities(const std::string& name) +getCapabilities(const std::string& deviceId) { - return jami::Manager::instance().getVideoManager().videoDeviceMonitor.getCapabilities(name); + return jami::Manager::instance().getVideoManager().videoDeviceMonitor.getCapabilities(deviceId); } std::string @@ -341,23 +341,23 @@ getDefaultDevice() } void -setDefaultDevice(const std::string& name) +setDefaultDevice(const std::string& deviceId) { - JAMI_DBG("Setting default device to %s", name.c_str()); - jami::Manager::instance().getVideoManager().videoDeviceMonitor.setDefaultDevice(name); + JAMI_DBG("Setting default device to %s", deviceId.c_str()); + jami::Manager::instance().getVideoManager().videoDeviceMonitor.setDefaultDevice(deviceId); jami::Manager::instance().saveConfig(); } void -setDeviceOrientation(const std::string& name, int angle) +setDeviceOrientation(const std::string& deviceId, int angle) { - jami::Manager::instance().getVideoManager().setDeviceOrientation(name, angle); + jami::Manager::instance().getVideoManager().setDeviceOrientation(deviceId, angle); } std::map<std::string, std::string> -getDeviceParams(const std::string& name) +getDeviceParams(const std::string& deviceId) { - auto params = jami::Manager::instance().getVideoManager().videoDeviceMonitor.getDeviceParams(name); + auto params = jami::Manager::instance().getVideoManager().videoDeviceMonitor.getDeviceParams(deviceId); std::stringstream width, height, rate; width << params.width; height << params.height; @@ -371,16 +371,16 @@ getDeviceParams(const std::string& name) } std::map<std::string, std::string> -getSettings(const std::string& name) +getSettings(const std::string& deviceId) { - return jami::Manager::instance().getVideoManager().videoDeviceMonitor.getSettings(name).to_map(); + return jami::Manager::instance().getVideoManager().videoDeviceMonitor.getSettings(deviceId).to_map(); } void -applySettings(const std::string& name, +applySettings(const std::string& deviceId, const std::map<std::string, std::string>& settings) { - jami::Manager::instance().getVideoManager().videoDeviceMonitor.applySettings(name, settings); + jami::Manager::instance().getVideoManager().videoDeviceMonitor.applySettings(deviceId, settings); jami::Manager::instance().saveConfig(); } @@ -650,9 +650,9 @@ getAudioInput(const std::string& id) } void -VideoManager::setDeviceOrientation(const std::string& name, int angle) +VideoManager::setDeviceOrientation(const std::string& deviceId, int angle) { - videoDeviceMonitor.setDeviceOrientation(name, angle); + videoDeviceMonitor.setDeviceOrientation(deviceId, angle); } } // namespace jami diff --git a/src/client/videomanager.h b/src/client/videomanager.h index 520fef040b..c12c686498 100644 --- a/src/client/videomanager.h +++ b/src/client/videomanager.h @@ -40,7 +40,7 @@ struct VideoManager { public: - void setDeviceOrientation(const std::string& name, int angle); + void setDeviceOrientation(const std::string& deviceId, int angle); /** * VideoManager acts as a cache of the active VideoInput. diff --git a/src/dring/videomanager_interface.h b/src/dring/videomanager_interface.h index a0b73478b1..c041c7cefb 100644 --- a/src/dring/videomanager_interface.h +++ b/src/dring/videomanager_interface.h @@ -163,14 +163,12 @@ struct DRING_PUBLIC AVSinkTarget { using VideoCapabilities = std::map<std::string, std::map<std::string, std::vector<std::string>>>; DRING_PUBLIC std::vector<std::string> getDeviceList(); -DRING_PUBLIC VideoCapabilities getCapabilities(const std::string& name); -DRING_PUBLIC std::map<std::string, std::string> getSettings(const std::string& name); -DRING_PUBLIC void applySettings(const std::string& name, const std::map<std::string, std::string>& settings); -DRING_PUBLIC void setDefaultDevice(const std::string& name); -DRING_PUBLIC void setDeviceOrientation(const std::string& name, int angle); - -DRING_PUBLIC std::map<std::string, std::string> getDeviceParams(const std::string& name); - +DRING_PUBLIC VideoCapabilities getCapabilities(const std::string& deviceId); +DRING_PUBLIC std::map<std::string, std::string> getSettings(const std::string& deviceId); +DRING_PUBLIC void applySettings(const std::string& deviceId, const std::map<std::string, std::string>& settings); +DRING_PUBLIC void setDefaultDevice(const std::string& deviceId); +DRING_PUBLIC void setDeviceOrientation(const std::string& deviceId, int angle); +DRING_PUBLIC std::map<std::string, std::string> getDeviceParams(const std::string& deviceId); DRING_PUBLIC std::string getDefaultDevice(); DRING_PUBLIC std::string getCurrentCodecName(const std::string& callID); DRING_PUBLIC void startCamera(); diff --git a/src/media/video/androidvideo/video_device_impl.cpp b/src/media/video/androidvideo/video_device_impl.cpp index 89f9515ea6..e47aa005ba 100644 --- a/src/media/video/androidvideo/video_device_impl.cpp +++ b/src/media/video/androidvideo/video_device_impl.cpp @@ -189,6 +189,7 @@ VideoDeviceImpl::setDeviceParams(const DeviceParams& params) VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>&) : deviceImpl_(new VideoDeviceImpl(path)) { + id_ = path; name = deviceImpl_->name; } diff --git a/src/media/video/iosvideo/video_device_impl.cpp b/src/media/video/iosvideo/video_device_impl.cpp index 2273be507a..be1acbf16a 100644 --- a/src/media/video/iosvideo/video_device_impl.cpp +++ b/src/media/video/iosvideo/video_device_impl.cpp @@ -179,7 +179,7 @@ VideoDeviceImpl::setDeviceParams(const DeviceParams& params) VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>& devInfo) : deviceImpl_(new VideoDeviceImpl(path, devInfo)) { - node_ = path; + id_ = path; name = deviceImpl_->name; } diff --git a/src/media/video/osxvideo/video_device_impl.mm b/src/media/video/osxvideo/video_device_impl.mm index 940deb05e8..45a3cbff54 100644 --- a/src/media/video/osxvideo/video_device_impl.mm +++ b/src/media/video/osxvideo/video_device_impl.mm @@ -42,7 +42,7 @@ class VideoDeviceImpl { */ VideoDeviceImpl(const std::string& path); - std::string device; + std::string id; std::string name; std::vector<std::string> getChannelList() const; @@ -64,7 +64,7 @@ class VideoDeviceImpl { }; VideoDeviceImpl::VideoDeviceImpl(const std::string& uniqueID) - : device(uniqueID) + : id(uniqueID) , current_size_(-1, -1) , avDevice_([AVCaptureDevice deviceWithUniqueID: [NSString stringWithCString:uniqueID.c_str() encoding:[NSString defaultCStringEncoding]]]) @@ -112,7 +112,7 @@ VideoDeviceImpl::getDeviceParams() const { DeviceParams params; params.name = [[avDevice_ localizedName] UTF8String]; - params.input = params.name; + params.input = [[avDevice_ localizedName] UTF8String]; params.framerate = rate_; params.format = "avfoundation"; params.pixel_format = "nv12"; @@ -155,7 +155,7 @@ VideoDeviceImpl::getChannelList() const VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>&) : deviceImpl_(new VideoDeviceImpl(path)) { - node_ = path; + id_ = path; name = deviceImpl_->name; } diff --git a/src/media/video/v4l2/video_device_impl.cpp b/src/media/video/v4l2/video_device_impl.cpp index 0709087a18..8542e45f66 100644 --- a/src/media/video/v4l2/video_device_impl.cpp +++ b/src/media/video/v4l2/video_device_impl.cpp @@ -125,7 +125,7 @@ public: */ VideoDeviceImpl(const std::string& path); - std::string device; + std::string id; std::string name; std::vector<std::string> getChannelList() const; @@ -431,14 +431,14 @@ VideoV4l2Channel::getSize(VideoSize s) const } VideoDeviceImpl::VideoDeviceImpl(const string& path) - : device(path) + : id(path) , name() , channels_() , channel_(-1, "") , size_(-1, -1) , rate_(-1, 1, 0) { - int fd = open(device.c_str(), O_RDWR); + int fd = open(id.c_str(), O_RDWR); if (fd == -1) throw std::runtime_error("could not open device"); @@ -544,7 +544,7 @@ VideoDeviceImpl::getDeviceParams() const { DeviceParams params; params.name = name; - params.input = device; + params.input = id; params.format = "video4linux2"; params.channel_name = channel_.name; params.channel = channel_.idx; @@ -571,7 +571,7 @@ VideoDeviceImpl::setDeviceParams(const DeviceParams& params) VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>&) : deviceImpl_(new VideoDeviceImpl(path)) { - node_ = path; + id_ = path; name = deviceImpl_->name; } diff --git a/src/media/video/video_base.cpp b/src/media/video/video_base.cpp index 9404aa7450..8389d0905f 100644 --- a/src/media/video/video_base.cpp +++ b/src/media/video/video_base.cpp @@ -83,6 +83,7 @@ extractString(const std::map<std::string, std::string>& settings, const std::str VideoSettings::VideoSettings(const std::map<std::string, std::string>& settings) { name = extractString(settings, "name"); + id = extractString(settings, "id"); channel = extractString(settings, "channel"); video_size = extractString(settings, "size"); framerate = extractString(settings, "rate"); @@ -93,6 +94,7 @@ VideoSettings::to_map() const { return { {"name", name}, + {"id", id}, {"size", video_size}, {"channel", channel}, {"rate", framerate} @@ -107,6 +109,7 @@ Node convert<jami::video::VideoSettings>::encode(const jami::video::VideoSettings& rhs) { Node node; node["name"] = rhs.name; + node["id"] = rhs.id; node["video_size"] = rhs.video_size; node["channel"] = rhs.channel; node["framerate"] = rhs.framerate; @@ -120,6 +123,7 @@ convert<jami::video::VideoSettings>::decode(const Node& node, jami::video::Video return false; } rhs.name = node["name"].as<std::string>(); + rhs.id = node["id"].as<std::string>(); rhs.video_size = node["video_size"].as<std::string>(); rhs.channel = node["channel"].as<std::string>(); rhs.framerate = node["framerate"].as<std::string>(); diff --git a/src/media/video/video_base.h b/src/media/video/video_base.h index d4e2e19e71..be09e4d9a4 100644 --- a/src/media/video/video_base.h +++ b/src/media/video/video_base.h @@ -96,6 +96,7 @@ struct VideoSettings std::map<std::string, std::string> to_map() const; + std::string id {}; std::string name {}; std::string channel {}; std::string video_size {}; diff --git a/src/media/video/video_device.h b/src/media/video/video_device.h index 16ea85fef8..6a88569231 100644 --- a/src/media/video/video_device.h +++ b/src/media/video/video_device.h @@ -56,7 +56,7 @@ public: */ std::string name {}; - const std::string& getNode() const { return node_; } + const std::string& getDeviceId() const { return id_; } /* * Get the 3 level deep tree of possible settings for the device. @@ -138,7 +138,8 @@ public: VideoSettings getSettings() const { auto params = getDeviceParams(); VideoSettings settings; - settings.name = params.name; + settings.name = name.empty() ? params.name : name; + settings.id = params.input; settings.channel = params.channel_name; settings.video_size = sizeToString(params.width, params.height); settings.framerate = jami::to_string(params.framerate.real()); @@ -155,6 +156,7 @@ public: void applySettings(VideoSettings settings) { DeviceParams params {}; params.name = settings.name; + params.input = settings.id; params.channel_name = settings.channel; auto size = sizeFromString(settings.channel, settings.video_size); params.width = size.first; @@ -222,7 +224,7 @@ private: /* * The device node, e.g. "/dev/video0". */ - std::string node_ {}; + std::string id_ {}; int orientation_ {0}; diff --git a/src/media/video/video_device_monitor.cpp b/src/media/video/video_device_monitor.cpp index 6bffe160ba..9500c16d5d 100644 --- a/src/media/video/video_device_monitor.cpp +++ b/src/media/video/video_device_monitor.cpp @@ -3,6 +3,7 @@ * * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> * Author: Vivien Didelot <vivien.didelot@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,18 +50,18 @@ vector<string> VideoDeviceMonitor::getDeviceList() const { std::lock_guard<std::mutex> l(lock_); - vector<string> names; - names.reserve(devices_.size()); + vector<string> ids; + ids.reserve(devices_.size()); for (const auto& dev : devices_) - names.emplace_back(dev.name); - return names; + ids.emplace_back(dev.getDeviceId()); + return ids; } DRing::VideoCapabilities -VideoDeviceMonitor::getCapabilities(const string& name) const +VideoDeviceMonitor::getCapabilities(const string& id) const { std::lock_guard<std::mutex> l(lock_); - const auto iter = findDeviceByName(name); + const auto iter = findDeviceById(id); if (iter == devices_.end()) return DRing::VideoCapabilities(); @@ -68,28 +69,28 @@ VideoDeviceMonitor::getCapabilities(const string& name) const } VideoSettings -VideoDeviceMonitor::getSettings(const string& name) +VideoDeviceMonitor::getSettings(const string& id) { std::lock_guard<std::mutex> l(lock_); - const auto itd = findPreferencesByName(name); - if (itd == preferences_.end()) + const auto prefIter = findPreferencesById(id); + if (prefIter == preferences_.end()) return VideoSettings(); - return *itd; + return *prefIter; } void -VideoDeviceMonitor::applySettings(const string& name, const VideoSettings& settings) +VideoDeviceMonitor::applySettings(const string& id, const VideoSettings& settings) { std::lock_guard<std::mutex> l(lock_); - const auto iter = findDeviceByName(name); + const auto iter = findDeviceById(id); if (iter == devices_.end()) return; iter->applySettings(settings); - auto it = findPreferencesByName(settings.name); + auto it = findPreferencesById(settings.id); if (it != preferences_.end()) (*it) = settings; } @@ -98,30 +99,33 @@ string VideoDeviceMonitor::getDefaultDevice() const { std::lock_guard<std::mutex> l(lock_); - return defaultDevice_; + const auto it = findDeviceById(defaultDevice_); + if (it == std::end(devices_)) + return {}; + return it->getDeviceId(); } std::string VideoDeviceMonitor::getMRLForDefaultDevice() const { std::lock_guard<std::mutex> l(lock_); - const auto it = findDeviceByName(defaultDevice_); + const auto it = findDeviceById(defaultDevice_); if(it == std::end(devices_)) return {}; static const std::string sep = DRing::Media::VideoProtocolPrefix::SEPARATOR; - return DRing::Media::VideoProtocolPrefix::CAMERA + sep + it->getSettings().name; + return DRing::Media::VideoProtocolPrefix::CAMERA + sep + it->getDeviceId(); } void -VideoDeviceMonitor::setDefaultDevice(const std::string& name) +VideoDeviceMonitor::setDefaultDevice(const std::string& id) { std::lock_guard<std::mutex> l(lock_); - const auto itDev = findDeviceByName(name); + const auto itDev = findDeviceById(id); if (itDev != devices_.end()) { - defaultDevice_ = itDev->name; + defaultDevice_ = itDev->getDeviceId(); // place it at the begining of the prefs - auto itPref = findPreferencesByName(name); + auto itPref = findPreferencesById(itDev->getDeviceId()); if (itPref != preferences_.end()) { auto settings = *itPref; preferences_.erase(itPref); @@ -133,64 +137,38 @@ VideoDeviceMonitor::setDefaultDevice(const std::string& name) } void -VideoDeviceMonitor::setDeviceOrientation(const std::string& name, int angle) +VideoDeviceMonitor::setDeviceOrientation(const std::string& id, int angle) { - const auto itd = findDeviceByName(name); + const auto itd = findDeviceById(id); if (itd != devices_.cend()) { itd->setOrientation(angle); } else { - JAMI_WARN("Can't find device %s to set orientation %d", name.c_str(), angle); + JAMI_WARN("Can't find device %s to set orientation %d", id.c_str(), angle); } } DeviceParams -VideoDeviceMonitor::getDeviceParams(const std::string& name) const +VideoDeviceMonitor::getDeviceParams(const std::string& id) const { std::lock_guard<std::mutex> l(lock_); - const auto itd = findDeviceByName(name); + const auto itd = findDeviceById(id); if (itd == devices_.cend()) return DeviceParams(); return itd->getDeviceParams(); } -static int -getNumber(const string &name, size_t *sharp) -{ - size_t len = name.length(); - // name is too short to be numbered - if (len < 3) - return -1; - - for (size_t c = len; c; --c) { - if (name[c] == '#') { - unsigned i; - if (sscanf(name.substr(c).c_str(), "#%u", &i) != 1) - return -1; - *sharp = c; - return i; - } - } - - return -1; -} - static void giveUniqueName(VideoDevice &dev, const vector<VideoDevice> &devices) { -start: - for (auto &item : devices) { - if (dev.name == item.name) { - size_t sharp; - int num = getNumber(dev.name, &sharp); - if (num < 0) // not numbered - dev.name += " #0"; - else { - stringstream ss; - ss << num + 1; - dev.name.replace(sharp + 1, ss.str().length(), ss.str()); - } - goto start; // we changed the name, let's look again if it is unique - } + std::string suffix; + uint64_t number = 2; + auto unique = true; + for (;; unique = static_cast<bool>(++number)) { + for (const auto& s : devices) + unique &= static_cast<bool>(s.name.compare(dev.name + suffix)); + if (unique) + return (void)(dev.name += suffix); + suffix = " (" + std::to_string(number) + ")"; } } @@ -203,15 +181,15 @@ notify() } void -VideoDeviceMonitor::addDevice(const string& node, const std::vector<std::map<std::string, std::string>>* devInfo) +VideoDeviceMonitor::addDevice(const string& id, const std::vector<std::map<std::string, std::string>>* devInfo) { try { std::lock_guard<std::mutex> l(lock_); - if (findDeviceByNode(node) != devices_.end()) + if (findDeviceById(id) != devices_.end()) return; // instantiate a new unique device - VideoDevice dev {node, *devInfo}; + VideoDevice dev { id, *devInfo}; if (dev.getChannelList().empty()) return; @@ -219,43 +197,42 @@ VideoDeviceMonitor::addDevice(const string& node, const std::vector<std::map<std giveUniqueName(dev, devices_); // restore its preferences if any, or store the defaults - auto it = findPreferencesByName(dev.name); - if (it != preferences_.end()) + auto it = findPreferencesById(id); + if (it != preferences_.end()) { dev.applySettings(*it); - else { + } else { dev.applySettings(dev.getDefaultSettings()); preferences_.emplace_back(dev.getSettings()); } // in case there is no default device on a fresh run if (defaultDevice_.empty()) - defaultDevice_ = dev.name; + defaultDevice_ = dev.getDeviceId(); devices_.emplace_back(std::move(dev)); } catch (const std::exception& e) { - JAMI_ERR("Failed to add device %s: %s", node.c_str(), e.what()); + JAMI_ERR("Failed to add device %s: %s", id.c_str(), e.what()); return; } notify(); } void -VideoDeviceMonitor::removeDevice(const string& node) +VideoDeviceMonitor::removeDevice(const string& id) { { std::lock_guard<std::mutex> l(lock_); - const auto it = findDeviceByNode(node); + const auto it = findDeviceById(id); if (it == devices_.end()) return; - auto removedDeviceName = it->name; devices_.erase(it); - if (defaultDevice_ == removedDeviceName) { + if (defaultDevice_.find(id) != std::string::npos) { if (devices_.size() == 0) { defaultDevice_.clear(); } else { - defaultDevice_ = devices_[0].name; + defaultDevice_ = devices_[0].getDeviceId(); } } } @@ -263,53 +240,36 @@ VideoDeviceMonitor::removeDevice(const string& node) } vector<VideoDevice>::iterator -VideoDeviceMonitor::findDeviceByName(const string& name) +VideoDeviceMonitor::findDeviceById(const string& id) { for (auto it = devices_.begin(); it != devices_.end(); ++it) - if (it->name == name) + if (it->getDeviceId().find(id) != std::string::npos) return it; return devices_.end(); } vector<VideoDevice>::const_iterator -VideoDeviceMonitor::findDeviceByName(const string& name) const +VideoDeviceMonitor::findDeviceById(const string& id) const { for (auto it = devices_.cbegin(); it != devices_.cend(); ++it) - if (it->name == name) - return it; - return devices_.cend(); -} - -vector<VideoDevice>::iterator -VideoDeviceMonitor::findDeviceByNode(const string& node) -{ - for (auto it = devices_.begin(); it != devices_.end(); ++it) - if (it->getNode().find(node) != std::string::npos) - return it; - return devices_.end(); -} - -vector<VideoDevice>::const_iterator -VideoDeviceMonitor::findDeviceByNode(const string& node) const -{ - for (auto it = devices_.cbegin(); it != devices_.cend(); ++it) - if (it->getNode().find(node) != std::string::npos) + if (it->getDeviceId().find(id) != std::string::npos) return it; return devices_.end(); } vector<VideoSettings>::iterator -VideoDeviceMonitor::findPreferencesByName(const string& name) +VideoDeviceMonitor::findPreferencesById(const string& id) { for (auto it = preferences_.begin(); it != preferences_.end(); ++it) - if (it->name == name) return it; + if (it->id.find(id) != std::string::npos) + return it; return preferences_.end(); } void VideoDeviceMonitor::overwritePreferences(const VideoSettings& settings) { - auto it = findPreferencesByName(settings.name); + auto it = findPreferencesById(settings.id); if (it != preferences_.end()) preferences_.erase(it); preferences_.emplace_back(settings); @@ -332,21 +292,23 @@ VideoDeviceMonitor::unserialize(const YAML::Node &in) const auto& devices = node["devices"]; for (const auto& dev : devices) { VideoSettings pref = dev.as<VideoSettings>(); - if (pref.name.empty()) + if (pref.id.empty()) continue; // discard malformed section overwritePreferences(pref); - auto itd = findDeviceByName(pref.name); + auto itd = findDeviceById(pref.id); if (itd != devices_.end()) itd->applySettings(pref); } // Restore the default device if present, or select the first one - const string pref = preferences_.empty() ? "" : preferences_[0].name; - const string first = devices_.empty() ? "" : devices_[0].name; - if (findDeviceByName(pref) != devices_.end()) - defaultDevice_ = pref; - else - defaultDevice_ = first; + const string prefId = preferences_.empty() ? "" : preferences_[0].id; + const string firstId = devices_.empty() ? "" : devices_[0].getDeviceId(); + const auto devIter = findDeviceById(prefId); + if (devIter != devices_.end()) { + defaultDevice_ = devIter->getDeviceId(); + } else { + defaultDevice_ = firstId; + } } -#pragma optimize("", on) + }} // namespace jami::video diff --git a/src/media/video/video_device_monitor.h b/src/media/video/video_device_monitor.h index ff2f1de1e1..40624b2e73 100644 --- a/src/media/video/video_device_monitor.h +++ b/src/media/video/video_device_monitor.h @@ -56,7 +56,7 @@ class VideoDeviceMonitor : public Serializable std::string getDefaultDevice() const; std::string getMRLForDefaultDevice() const; void setDefaultDevice(const std::string& name); - void setDeviceOrientation(const std::string& name, int angle); + void setDeviceOrientation(const std::string& id, int angle); void addDevice(const std::string &node, const std::vector<std::map<std::string, std::string>>* devInfo=nullptr); void removeDevice(const std::string &node); @@ -83,7 +83,7 @@ class VideoDeviceMonitor : public Serializable std::vector<VideoSettings> preferences_; void overwritePreferences(const VideoSettings& settings); - std::vector<VideoSettings>::iterator findPreferencesByName(const std::string& name); + std::vector<VideoSettings>::iterator findPreferencesById(const std::string& id); /* * Vector containing the video devices. @@ -91,10 +91,8 @@ class VideoDeviceMonitor : public Serializable std::vector<VideoDevice> devices_; std::string defaultDevice_ = ""; - std::vector<VideoDevice>::iterator findDeviceByName(const std::string& name); - std::vector<VideoDevice>::const_iterator findDeviceByName(const std::string& name) const; - std::vector<VideoDevice>::iterator findDeviceByNode(const std::string& node); - std::vector<VideoDevice>::const_iterator findDeviceByNode(const std::string& node) const; + std::vector<VideoDevice>::iterator findDeviceById(const std::string& id); + std::vector<VideoDevice>::const_iterator findDeviceById(const std::string& id) const; std::unique_ptr<VideoDeviceMonitorImpl> monitorImpl_; diff --git a/src/media/video/winvideo/video_device_impl.cpp b/src/media/video/winvideo/video_device_impl.cpp index 44155cb268..72ec9f56a2 100644 --- a/src/media/video/winvideo/video_device_impl.cpp +++ b/src/media/video/winvideo/video_device_impl.cpp @@ -43,8 +43,8 @@ class VideoDeviceImpl { /** * @throw std::runtime_error */ - VideoDeviceImpl(const std::string& path); - std::string device; + VideoDeviceImpl(const std::string& id); + std::string id; std::string name; std::vector<std::string> getChannelList() const; @@ -66,8 +66,8 @@ class VideoDeviceImpl { void fail(const std::string& error); }; -VideoDeviceImpl::VideoDeviceImpl(const std::string& path) - : device(path) +VideoDeviceImpl::VideoDeviceImpl(const std::string& id) + : id(id) , name() , cInterface(new CaptureGraphInterfaces()) { @@ -148,11 +148,11 @@ VideoDeviceImpl::setup() // We want to get the capabilities of a device with the unique_name // that corresponds to what was enumerated by the video device monitor. - if (unique_name.find(this->device) == std::string::npos) { + if (unique_name.find(this->id) == std::string::npos) { continue; } - this->device = unique_name; + this->id = unique_name; // get friendly name VARIANT var; @@ -257,7 +257,7 @@ VideoDeviceImpl::getDeviceParams() const DeviceParams params; params.name = name; - params.input = device; + params.input = id; params.format = "dshow"; AM_MEDIA_TYPE *pmt; @@ -316,7 +316,7 @@ VideoDeviceImpl::getChannelList() const VideoDevice::VideoDevice(const std::string& path, const std::vector<std::map<std::string, std::string>>&) : deviceImpl_(new VideoDeviceImpl(path)) { - node_ = path; + id_ = path; name = deviceImpl_->name; } diff --git a/src/media/video/winvideo/video_device_monitor_impl.cpp b/src/media/video/winvideo/video_device_monitor_impl.cpp index 2230d942b8..1ae45caa99 100644 --- a/src/media/video/winvideo/video_device_monitor_impl.cpp +++ b/src/media/video/winvideo/video_device_monitor_impl.cpp @@ -166,9 +166,9 @@ VideoDeviceMonitorImpl::WinProcCallback(HWND hWnd, UINT message, WPARAM wParam, if (pThis = reinterpret_cast<VideoDeviceMonitorImpl*>(GetWindowLongPtr(hWnd, GWLP_USERDATA))) { if (wParam == DBT_DEVICEARRIVAL) { auto captureDeviceList = pThis->enumerateVideoInputDevices(); - for (auto node : captureDeviceList) { - if (node.find(unique_name) != std::string::npos) - pThis->monitor_->addDevice(node); + for (auto id : captureDeviceList) { + if (id.find(unique_name) != std::string::npos) + pThis->monitor_->addDevice(id); } } else if (wParam == DBT_DEVICEREMOVECOMPLETE) { pThis->monitor_->removeDevice(unique_name); -- GitLab