summary refs log tree commit diff
path: root/src/CallDevices.cpp
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-09-18 00:22:33 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2021-09-18 00:45:50 +0200
commitcfca7157b98c9dc8e0852fe6484bc3f75008af7d (patch)
tree32b92340908a9374214ec7b84c1fac7ea338f56d /src/CallDevices.cpp
parentMerge pull request #728 from Thulinma/goto (diff)
downloadnheko-cfca7157b98c9dc8e0852fe6484bc3f75008af7d.tar.xz
Change indentation to 4 spaces
Diffstat (limited to 'src/CallDevices.cpp')
-rw-r--r--src/CallDevices.cpp439
1 files changed, 214 insertions, 225 deletions
diff --git a/src/CallDevices.cpp b/src/CallDevices.cpp

index 825d2f72..be185470 100644 --- a/src/CallDevices.cpp +++ b/src/CallDevices.cpp
@@ -27,20 +27,20 @@ namespace { struct AudioSource { - std::string name; - GstDevice *device; + std::string name; + GstDevice *device; }; struct VideoSource { - struct Caps - { - std::string resolution; - std::vector<std::string> frameRates; - }; - std::string name; - GstDevice *device; - std::vector<Caps> caps; + struct Caps + { + std::string resolution; + std::vector<std::string> frameRates; + }; + std::string name; + GstDevice *device; + std::vector<Caps> caps; }; std::vector<AudioSource> audioSources_; @@ -50,315 +50,304 @@ using FrameRate = std::pair<int, int>; std::optional<FrameRate> getFrameRate(const GValue *value) { - if (GST_VALUE_HOLDS_FRACTION(value)) { - gint num = gst_value_get_fraction_numerator(value); - gint den = gst_value_get_fraction_denominator(value); - return FrameRate{num, den}; - } - return std::nullopt; + if (GST_VALUE_HOLDS_FRACTION(value)) { + gint num = gst_value_get_fraction_numerator(value); + gint den = gst_value_get_fraction_denominator(value); + return FrameRate{num, den}; + } + return std::nullopt; } void addFrameRate(std::vector<std::string> &rates, const FrameRate &rate) { - constexpr double minimumFrameRate = 15.0; - if (static_cast<double>(rate.first) / rate.second >= minimumFrameRate) - rates.push_back(std::to_string(rate.first) + "/" + std::to_string(rate.second)); + constexpr double minimumFrameRate = 15.0; + if (static_cast<double>(rate.first) / rate.second >= minimumFrameRate) + rates.push_back(std::to_string(rate.first) + "/" + std::to_string(rate.second)); } void setDefaultDevice(bool isVideo) { - auto settings = ChatPage::instance()->userSettings(); - if (isVideo && settings->camera().isEmpty()) { - const VideoSource &camera = videoSources_.front(); - settings->setCamera(QString::fromStdString(camera.name)); - settings->setCameraResolution( - QString::fromStdString(camera.caps.front().resolution)); - settings->setCameraFrameRate( - QString::fromStdString(camera.caps.front().frameRates.front())); - } else if (!isVideo && settings->microphone().isEmpty()) { - settings->setMicrophone(QString::fromStdString(audioSources_.front().name)); - } + auto settings = ChatPage::instance()->userSettings(); + if (isVideo && settings->camera().isEmpty()) { + const VideoSource &camera = videoSources_.front(); + settings->setCamera(QString::fromStdString(camera.name)); + settings->setCameraResolution(QString::fromStdString(camera.caps.front().resolution)); + settings->setCameraFrameRate( + QString::fromStdString(camera.caps.front().frameRates.front())); + } else if (!isVideo && settings->microphone().isEmpty()) { + settings->setMicrophone(QString::fromStdString(audioSources_.front().name)); + } } void addDevice(GstDevice *device) { - if (!device) - return; - - gchar *name = gst_device_get_display_name(device); - gchar *type = gst_device_get_device_class(device); - bool isVideo = !std::strncmp(type, "Video", 5); - g_free(type); - nhlog::ui()->debug("WebRTC: {} device added: {}", isVideo ? "video" : "audio", name); - if (!isVideo) { - audioSources_.push_back({name, device}); - g_free(name); - setDefaultDevice(false); - return; - } + if (!device) + return; - GstCaps *gstcaps = gst_device_get_caps(device); - if (!gstcaps) { - nhlog::ui()->debug("WebRTC: unable to get caps for {}", name); - g_free(name); - return; - } + gchar *name = gst_device_get_display_name(device); + gchar *type = gst_device_get_device_class(device); + bool isVideo = !std::strncmp(type, "Video", 5); + g_free(type); + nhlog::ui()->debug("WebRTC: {} device added: {}", isVideo ? "video" : "audio", name); + if (!isVideo) { + audioSources_.push_back({name, device}); + g_free(name); + setDefaultDevice(false); + return; + } - VideoSource source{name, device, {}}; + GstCaps *gstcaps = gst_device_get_caps(device); + if (!gstcaps) { + nhlog::ui()->debug("WebRTC: unable to get caps for {}", name); g_free(name); - guint nCaps = gst_caps_get_size(gstcaps); - for (guint i = 0; i < nCaps; ++i) { - GstStructure *structure = gst_caps_get_structure(gstcaps, i); - const gchar *struct_name = gst_structure_get_name(structure); - if (!std::strcmp(struct_name, "video/x-raw")) { - gint widthpx, heightpx; - if (gst_structure_get(structure, - "width", - G_TYPE_INT, - &widthpx, - "height", - G_TYPE_INT, - &heightpx, - nullptr)) { - VideoSource::Caps caps; - caps.resolution = - std::to_string(widthpx) + "x" + std::to_string(heightpx); - const GValue *value = - gst_structure_get_value(structure, "framerate"); - if (auto fr = getFrameRate(value); fr) - addFrameRate(caps.frameRates, *fr); - else if (GST_VALUE_HOLDS_FRACTION_RANGE(value)) { - addFrameRate( - caps.frameRates, - *getFrameRate(gst_value_get_fraction_range_min(value))); - addFrameRate( - caps.frameRates, - *getFrameRate(gst_value_get_fraction_range_max(value))); - } else if (GST_VALUE_HOLDS_LIST(value)) { - guint nRates = gst_value_list_get_size(value); - for (guint j = 0; j < nRates; ++j) { - const GValue *rate = - gst_value_list_get_value(value, j); - if (auto frate = getFrameRate(rate); frate) - addFrameRate(caps.frameRates, *frate); - } - } - if (!caps.frameRates.empty()) - source.caps.push_back(std::move(caps)); - } + return; + } + + VideoSource source{name, device, {}}; + g_free(name); + guint nCaps = gst_caps_get_size(gstcaps); + for (guint i = 0; i < nCaps; ++i) { + GstStructure *structure = gst_caps_get_structure(gstcaps, i); + const gchar *struct_name = gst_structure_get_name(structure); + if (!std::strcmp(struct_name, "video/x-raw")) { + gint widthpx, heightpx; + if (gst_structure_get(structure, + "width", + G_TYPE_INT, + &widthpx, + "height", + G_TYPE_INT, + &heightpx, + nullptr)) { + VideoSource::Caps caps; + caps.resolution = std::to_string(widthpx) + "x" + std::to_string(heightpx); + const GValue *value = gst_structure_get_value(structure, "framerate"); + if (auto fr = getFrameRate(value); fr) + addFrameRate(caps.frameRates, *fr); + else if (GST_VALUE_HOLDS_FRACTION_RANGE(value)) { + addFrameRate(caps.frameRates, + *getFrameRate(gst_value_get_fraction_range_min(value))); + addFrameRate(caps.frameRates, + *getFrameRate(gst_value_get_fraction_range_max(value))); + } else if (GST_VALUE_HOLDS_LIST(value)) { + guint nRates = gst_value_list_get_size(value); + for (guint j = 0; j < nRates; ++j) { + const GValue *rate = gst_value_list_get_value(value, j); + if (auto frate = getFrameRate(rate); frate) + addFrameRate(caps.frameRates, *frate); + } } + if (!caps.frameRates.empty()) + source.caps.push_back(std::move(caps)); + } } - gst_caps_unref(gstcaps); - videoSources_.push_back(std::move(source)); - setDefaultDevice(true); + } + gst_caps_unref(gstcaps); + videoSources_.push_back(std::move(source)); + setDefaultDevice(true); } template<typename T> bool removeDevice(T &sources, GstDevice *device, bool changed) { - if (auto it = std::find_if(sources.begin(), - sources.end(), - [device](const auto &s) { return s.device == device; }); - it != sources.end()) { - nhlog::ui()->debug(std::string("WebRTC: device ") + - (changed ? "changed: " : "removed: ") + "{}", - it->name); - gst_object_unref(device); - sources.erase(it); - return true; - } - return false; + if (auto it = std::find_if( + sources.begin(), sources.end(), [device](const auto &s) { return s.device == device; }); + it != sources.end()) { + nhlog::ui()->debug( + std::string("WebRTC: device ") + (changed ? "changed: " : "removed: ") + "{}", it->name); + gst_object_unref(device); + sources.erase(it); + return true; + } + return false; } void removeDevice(GstDevice *device, bool changed) { - if (device) { - if (removeDevice(audioSources_, device, changed) || - removeDevice(videoSources_, device, changed)) - return; - } + if (device) { + if (removeDevice(audioSources_, device, changed) || + removeDevice(videoSources_, device, changed)) + return; + } } gboolean newBusMessage(GstBus *bus G_GNUC_UNUSED, GstMessage *msg, gpointer user_data G_GNUC_UNUSED) { - switch (GST_MESSAGE_TYPE(msg)) { - case GST_MESSAGE_DEVICE_ADDED: { - GstDevice *device; - gst_message_parse_device_added(msg, &device); - addDevice(device); - emit CallDevices::instance().devicesChanged(); - break; - } - case GST_MESSAGE_DEVICE_REMOVED: { - GstDevice *device; - gst_message_parse_device_removed(msg, &device); - removeDevice(device, false); - emit CallDevices::instance().devicesChanged(); - break; - } - case GST_MESSAGE_DEVICE_CHANGED: { - GstDevice *device; - GstDevice *oldDevice; - gst_message_parse_device_changed(msg, &device, &oldDevice); - removeDevice(oldDevice, true); - addDevice(device); - break; - } - default: - break; - } - return TRUE; + switch (GST_MESSAGE_TYPE(msg)) { + case GST_MESSAGE_DEVICE_ADDED: { + GstDevice *device; + gst_message_parse_device_added(msg, &device); + addDevice(device); + emit CallDevices::instance().devicesChanged(); + break; + } + case GST_MESSAGE_DEVICE_REMOVED: { + GstDevice *device; + gst_message_parse_device_removed(msg, &device); + removeDevice(device, false); + emit CallDevices::instance().devicesChanged(); + break; + } + case GST_MESSAGE_DEVICE_CHANGED: { + GstDevice *device; + GstDevice *oldDevice; + gst_message_parse_device_changed(msg, &device, &oldDevice); + removeDevice(oldDevice, true); + addDevice(device); + break; + } + default: + break; + } + return TRUE; } template<typename T> std::vector<std::string> deviceNames(T &sources, const std::string &defaultDevice) { - std::vector<std::string> ret; - ret.reserve(sources.size()); - for (const auto &s : sources) - ret.push_back(s.name); + std::vector<std::string> ret; + ret.reserve(sources.size()); + for (const auto &s : sources) + ret.push_back(s.name); - // move default device to top of the list - if (auto it = std::find(ret.begin(), ret.end(), defaultDevice); it != ret.end()) - std::swap(ret.front(), *it); + // move default device to top of the list + if (auto it = std::find(ret.begin(), ret.end(), defaultDevice); it != ret.end()) + std::swap(ret.front(), *it); - return ret; + return ret; } std::optional<VideoSource> getVideoSource(const std::string &cameraName) { - if (auto it = std::find_if(videoSources_.cbegin(), - videoSources_.cend(), - [&cameraName](const auto &s) { return s.name == cameraName; }); - it != videoSources_.cend()) { - return *it; - } - return std::nullopt; + if (auto it = std::find_if(videoSources_.cbegin(), + videoSources_.cend(), + [&cameraName](const auto &s) { return s.name == cameraName; }); + it != videoSources_.cend()) { + return *it; + } + return std::nullopt; } std::pair<int, int> tokenise(std::string_view str, char delim) { - std::pair<int, int> ret; - ret.first = std::atoi(str.data()); - auto pos = str.find_first_of(delim); - ret.second = std::atoi(str.data() + pos + 1); - return ret; + std::pair<int, int> ret; + ret.first = std::atoi(str.data()); + auto pos = str.find_first_of(delim); + ret.second = std::atoi(str.data() + pos + 1); + return ret; } } void CallDevices::init() { - static GstDeviceMonitor *monitor = nullptr; - if (!monitor) { - monitor = gst_device_monitor_new(); - GstCaps *caps = gst_caps_new_empty_simple("audio/x-raw"); - gst_device_monitor_add_filter(monitor, "Audio/Source", caps); - gst_device_monitor_add_filter(monitor, "Audio/Duplex", caps); - gst_caps_unref(caps); - caps = gst_caps_new_empty_simple("video/x-raw"); - gst_device_monitor_add_filter(monitor, "Video/Source", caps); - gst_device_monitor_add_filter(monitor, "Video/Duplex", caps); - gst_caps_unref(caps); + static GstDeviceMonitor *monitor = nullptr; + if (!monitor) { + monitor = gst_device_monitor_new(); + GstCaps *caps = gst_caps_new_empty_simple("audio/x-raw"); + gst_device_monitor_add_filter(monitor, "Audio/Source", caps); + gst_device_monitor_add_filter(monitor, "Audio/Duplex", caps); + gst_caps_unref(caps); + caps = gst_caps_new_empty_simple("video/x-raw"); + gst_device_monitor_add_filter(monitor, "Video/Source", caps); + gst_device_monitor_add_filter(monitor, "Video/Duplex", caps); + gst_caps_unref(caps); - GstBus *bus = gst_device_monitor_get_bus(monitor); - gst_bus_add_watch(bus, newBusMessage, nullptr); - gst_object_unref(bus); - if (!gst_device_monitor_start(monitor)) { - nhlog::ui()->error("WebRTC: failed to start device monitor"); - return; - } + GstBus *bus = gst_device_monitor_get_bus(monitor); + gst_bus_add_watch(bus, newBusMessage, nullptr); + gst_object_unref(bus); + if (!gst_device_monitor_start(monitor)) { + nhlog::ui()->error("WebRTC: failed to start device monitor"); + return; } + } } bool CallDevices::haveMic() const { - return !audioSources_.empty(); + return !audioSources_.empty(); } bool CallDevices::haveCamera() const { - return !videoSources_.empty(); + return !videoSources_.empty(); } std::vector<std::string> CallDevices::names(bool isVideo, const std::string &defaultDevice) const { - return isVideo ? deviceNames(videoSources_, defaultDevice) - : deviceNames(audioSources_, defaultDevice); + return isVideo ? deviceNames(videoSources_, defaultDevice) + : deviceNames(audioSources_, defaultDevice); } std::vector<std::string> CallDevices::resolutions(const std::string &cameraName) const { - std::vector<std::string> ret; - if (auto s = getVideoSource(cameraName); s) { - ret.reserve(s->caps.size()); - for (const auto &c : s->caps) - ret.push_back(c.resolution); - } - return ret; + std::vector<std::string> ret; + if (auto s = getVideoSource(cameraName); s) { + ret.reserve(s->caps.size()); + for (const auto &c : s->caps) + ret.push_back(c.resolution); + } + return ret; } std::vector<std::string> CallDevices::frameRates(const std::string &cameraName, const std::string &resolution) const { - if (auto s = getVideoSource(cameraName); s) { - if (auto it = - std::find_if(s->caps.cbegin(), + if (auto s = getVideoSource(cameraName); s) { + if (auto it = std::find_if(s->caps.cbegin(), s->caps.cend(), [&](const auto &c) { return c.resolution == resolution; }); - it != s->caps.cend()) - return it->frameRates; - } - return {}; + it != s->caps.cend()) + return it->frameRates; + } + return {}; } GstDevice * CallDevices::audioDevice() const { - std::string name = ChatPage::instance()->userSettings()->microphone().toStdString(); - if (auto it = std::find_if(audioSources_.cbegin(), - audioSources_.cend(), - [&name](const auto &s) { return s.name == name; }); - it != audioSources_.cend()) { - nhlog::ui()->debug("WebRTC: microphone: {}", name); - return it->device; - } else { - nhlog::ui()->error("WebRTC: unknown microphone: {}", name); - return nullptr; - } + std::string name = ChatPage::instance()->userSettings()->microphone().toStdString(); + if (auto it = std::find_if(audioSources_.cbegin(), + audioSources_.cend(), + [&name](const auto &s) { return s.name == name; }); + it != audioSources_.cend()) { + nhlog::ui()->debug("WebRTC: microphone: {}", name); + return it->device; + } else { + nhlog::ui()->error("WebRTC: unknown microphone: {}", name); + return nullptr; + } } GstDevice * CallDevices::videoDevice(std::pair<int, int> &resolution, std::pair<int, int> &frameRate) const { - auto settings = ChatPage::instance()->userSettings(); - std::string name = settings->camera().toStdString(); - if (auto s = getVideoSource(name); s) { - nhlog::ui()->debug("WebRTC: camera: {}", name); - resolution = tokenise(settings->cameraResolution().toStdString(), 'x'); - frameRate = tokenise(settings->cameraFrameRate().toStdString(), '/'); - nhlog::ui()->debug( - "WebRTC: camera resolution: {}x{}", resolution.first, resolution.second); - nhlog::ui()->debug( - "WebRTC: camera frame rate: {}/{}", frameRate.first, frameRate.second); - return s->device; - } else { - nhlog::ui()->error("WebRTC: unknown camera: {}", name); - return nullptr; - } + auto settings = ChatPage::instance()->userSettings(); + std::string name = settings->camera().toStdString(); + if (auto s = getVideoSource(name); s) { + nhlog::ui()->debug("WebRTC: camera: {}", name); + resolution = tokenise(settings->cameraResolution().toStdString(), 'x'); + frameRate = tokenise(settings->cameraFrameRate().toStdString(), '/'); + nhlog::ui()->debug("WebRTC: camera resolution: {}x{}", resolution.first, resolution.second); + nhlog::ui()->debug("WebRTC: camera frame rate: {}/{}", frameRate.first, frameRate.second); + return s->device; + } else { + nhlog::ui()->error("WebRTC: unknown camera: {}", name); + return nullptr; + } } #else @@ -366,31 +355,31 @@ CallDevices::videoDevice(std::pair<int, int> &resolution, std::pair<int, int> &f bool CallDevices::haveMic() const { - return false; + return false; } bool CallDevices::haveCamera() const { - return false; + return false; } std::vector<std::string> CallDevices::names(bool, const std::string &) const { - return {}; + return {}; } std::vector<std::string> CallDevices::resolutions(const std::string &) const { - return {}; + return {}; } std::vector<std::string> CallDevices::frameRates(const std::string &, const std::string &) const { - return {}; + return {}; } #endif