mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-01-31 01:13:04 +09:00
Update to handle new gsr --info output, remove general section from streaming
This commit is contained in:
10
TODO
10
TODO
@@ -250,6 +250,12 @@ Sometimes when opening gpu screen recorder ui gsr-global-hotkeys incorrectly det
|
||||
|
||||
When running replay for a long time and then stopping it it takes a while. Improve this.
|
||||
|
||||
When adding webcamera make replay auto start wait for camera to be available (when /dev/video device exists and can be initialized), just like audio device.
|
||||
Make it possible to resize webcam box from top left, top right and bottom left as well.
|
||||
|
||||
Make it possible to resize webcam box from top left, top right and bottom left as well.
|
||||
Add kick streaming option (add /app at the end of the url).
|
||||
|
||||
The flatpak version can for some get stuck at shutdown when instant replay is running. It only happens in the flatpak version and only when instant replay is running and it happens always. Manual SIGINT on gsr-ui stops gsr-ui properly, so why does it fail when shutting down the computer when the systemd stop signal is SIGINT? Maybe its related to the flatpak version being launched through gsr-gtk. I cant personally reproduce it.
|
||||
|
||||
Show warning in the UI (with a warning icon) when adding audio output device and application audio in the same audio track.
|
||||
|
||||
Redesign the UI to allow capturing multiple video sources. Move webcam to capture sources as well then. Maybe design the UI to work more like obs studio then, where you start recording and then add sources at capture time, with a preview.
|
||||
|
||||
@@ -25,9 +25,9 @@ namespace gsr {
|
||||
bool png = false;
|
||||
};
|
||||
|
||||
struct SupportedCameraPixelFormats {
|
||||
bool yuyv = false;
|
||||
bool mjpeg = false;
|
||||
enum GsrCameraPixelFormat {
|
||||
YUYV,
|
||||
MJPEG
|
||||
};
|
||||
|
||||
struct GsrMonitor {
|
||||
@@ -35,10 +35,16 @@ namespace gsr {
|
||||
mgl::vec2i size;
|
||||
};
|
||||
|
||||
struct GsrCameraSetup {
|
||||
mgl::vec2i resolution;
|
||||
int fps;
|
||||
//GsrCameraPixelFormat pixel_format;
|
||||
};
|
||||
|
||||
struct GsrCamera {
|
||||
std::string path;
|
||||
mgl::vec2i size;
|
||||
SupportedCameraPixelFormats supported_pixel_formats;
|
||||
std::vector<GsrCameraSetup> yuyv_setups;
|
||||
std::vector<GsrCameraSetup> mjpeg_setups;
|
||||
};
|
||||
|
||||
struct GsrVersion {
|
||||
|
||||
@@ -237,5 +237,6 @@ namespace gsr {
|
||||
mgl::vec2f webcam_box_size_resize_start;
|
||||
|
||||
std::optional<GsrCamera> selected_camera;
|
||||
std::optional<GsrCameraSetup> selected_camera_setup;
|
||||
};
|
||||
}
|
||||
@@ -310,32 +310,34 @@ namespace gsr {
|
||||
};
|
||||
}
|
||||
|
||||
static SupportedCameraPixelFormats parse_supported_camera_pixel_formats(std::string_view line) {
|
||||
SupportedCameraPixelFormats result;
|
||||
string_split_char(line, ',', [&](std::string_view column) {
|
||||
if(column == "yuyv")
|
||||
result.yuyv = true;
|
||||
else if(column == "mjpeg")
|
||||
result.mjpeg = true;
|
||||
static bool parse_camera_pixel_format(std::string_view line, GsrCameraPixelFormat &pixel_format) {
|
||||
if(line == "yuyv") {
|
||||
pixel_format = YUYV;
|
||||
return true;
|
||||
});
|
||||
return result;
|
||||
} else if(line == "mjpeg") {
|
||||
pixel_format = MJPEG;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static std::optional<GsrCamera> capture_option_line_to_camera(std::string_view line) {
|
||||
std::optional<GsrCamera> camera;
|
||||
static bool capture_option_line_to_camera(std::string_view line, std::string &path, GsrCameraSetup &camera_setup, GsrCameraPixelFormat &pixel_format) {
|
||||
const std::optional<KeyValue3> key_value3 = parse_3(line);
|
||||
if(!key_value3)
|
||||
return camera;
|
||||
return false;
|
||||
|
||||
path = key_value3->value1;
|
||||
|
||||
mgl::vec2i size;
|
||||
char value_buffer[256];
|
||||
snprintf(value_buffer, sizeof(value_buffer), "%.*s", (int)key_value3->value2.size(), key_value3->value2.data());
|
||||
if(sscanf(value_buffer, "%dx%d", &size.x, &size.y) != 2)
|
||||
return camera;
|
||||
if(sscanf(value_buffer, "%dx%d@%dhz", &camera_setup.resolution.x, &camera_setup.resolution.y, &camera_setup.fps) != 3)
|
||||
return false;
|
||||
|
||||
camera = GsrCamera{std::string(key_value3->value1), size, parse_supported_camera_pixel_formats(key_value3->value3)};
|
||||
return camera;
|
||||
if(!parse_camera_pixel_format(key_value3->value3, pixel_format))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::optional<GsrMonitor> capture_option_line_to_monitor(std::string_view line) {
|
||||
@@ -354,6 +356,37 @@ namespace gsr {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
static GsrCamera* get_gsr_camera_by_path(std::vector<GsrCamera> &cameras, const std::string &path) {
|
||||
for(GsrCamera &camera : cameras) {
|
||||
if(camera.path == path)
|
||||
return &camera;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void parse_camera_line(std::string_view line, std::vector<GsrCamera> &cameras) {
|
||||
std::string camera_path;
|
||||
GsrCameraSetup camera_setup;
|
||||
GsrCameraPixelFormat pixel_format;
|
||||
if(!capture_option_line_to_camera(line, camera_path, camera_setup, pixel_format))
|
||||
return;
|
||||
|
||||
GsrCamera *existing_camera = get_gsr_camera_by_path(cameras, camera_path);
|
||||
if(!existing_camera) {
|
||||
cameras.push_back(GsrCamera{camera_path, std::vector<GsrCameraSetup>{}, std::vector<GsrCameraSetup>{}});
|
||||
existing_camera = &cameras.back();
|
||||
}
|
||||
|
||||
switch(pixel_format) {
|
||||
case YUYV:
|
||||
existing_camera->yuyv_setups.push_back(camera_setup);
|
||||
break;
|
||||
case MJPEG:
|
||||
existing_camera->mjpeg_setups.push_back(camera_setup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_capture_options_line(SupportedCaptureOptions &capture_options, std::string_view line) {
|
||||
if(line == "window") {
|
||||
capture_options.window = true;
|
||||
@@ -364,9 +397,7 @@ namespace gsr {
|
||||
} else if(line == "portal") {
|
||||
capture_options.portal = true;
|
||||
} else if(!line.empty() && line[0] == '/') {
|
||||
std::optional<GsrCamera> camera = capture_option_line_to_camera(line);
|
||||
if(camera)
|
||||
capture_options.cameras.push_back(std::move(camera.value()));
|
||||
parse_camera_line(line, capture_options.cameras);
|
||||
} else {
|
||||
std::optional<GsrMonitor> monitor = capture_option_line_to_monitor(line);
|
||||
if(monitor)
|
||||
@@ -414,9 +445,7 @@ namespace gsr {
|
||||
}
|
||||
|
||||
string_split_char(stdout_str, '\n', [&](std::string_view line) {
|
||||
std::optional<GsrCamera> camera = capture_option_line_to_camera(line);
|
||||
if(camera)
|
||||
cameras.push_back(std::move(camera.value()));
|
||||
parse_camera_line(line, cameras);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
@@ -1278,7 +1278,7 @@ namespace gsr {
|
||||
if(recording_status == RecordingStatus::RECORD)
|
||||
show_notification("Recording settings have been modified.\nYou may need to restart recording to apply the changes.", notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD);
|
||||
|
||||
update_led_indicator_after_settings_change();
|
||||
update_led_indicator_after_settings_change();
|
||||
};
|
||||
page_stack.push(std::move(record_settings_page));
|
||||
} else if(id == "pause") {
|
||||
|
||||
@@ -205,6 +205,7 @@ namespace gsr {
|
||||
|
||||
webcam_sources_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) {
|
||||
selected_camera = std::nullopt;
|
||||
selected_camera_setup = std::nullopt;
|
||||
webcam_video_format_box_ptr->clear_items();
|
||||
if(id == "") {
|
||||
webcam_body_list_ptr->set_visible(false);
|
||||
@@ -220,14 +221,26 @@ namespace gsr {
|
||||
webcam_body_list_ptr->set_visible(true);
|
||||
webcam_video_format_box_ptr->add_item("Auto (recommended)", "auto");
|
||||
|
||||
if(it->supported_pixel_formats.yuyv)
|
||||
if(!it->yuyv_setups.empty())
|
||||
webcam_video_format_box_ptr->add_item("YUYV", "yuyv");
|
||||
|
||||
if(it->supported_pixel_formats.mjpeg)
|
||||
if(!it->mjpeg_setups.empty())
|
||||
webcam_video_format_box_ptr->add_item("Motion-JPEG", "mjpeg");
|
||||
|
||||
webcam_video_format_box_ptr->set_selected_item(get_current_record_options().webcam_video_format);
|
||||
selected_camera = *it;
|
||||
|
||||
// TODO: Set from config
|
||||
if(webcam_video_format_box_ptr->get_selected_id() == "yuyv" && !it->yuyv_setups.empty())
|
||||
selected_camera_setup = selected_camera->yuyv_setups.front();
|
||||
else if(webcam_video_format_box_ptr->get_selected_id() == "mjpeg" && !it->mjpeg_setups.empty())
|
||||
selected_camera_setup = selected_camera->mjpeg_setups.front();
|
||||
else if(webcam_video_format_box_ptr->get_selected_id() == "auto") {
|
||||
if(!it->mjpeg_setups.empty())
|
||||
selected_camera_setup = selected_camera->mjpeg_setups.front();
|
||||
else if(!it->yuyv_setups.empty())
|
||||
selected_camera_setup = selected_camera->yuyv_setups.front();
|
||||
}
|
||||
};
|
||||
|
||||
ll->add_widget(std::move(combobox));
|
||||
@@ -261,13 +274,13 @@ namespace gsr {
|
||||
|
||||
auto camera_location_widget = std::make_unique<CustomRendererWidget>(camera_screen_size);
|
||||
camera_location_widget->draw_handler = [this, screen_border_size, screen_border](mgl::Window &window, mgl::vec2f pos, mgl::vec2f size) {
|
||||
if(!selected_camera.has_value())
|
||||
if(!selected_camera.has_value() || !selected_camera_setup.has_value())
|
||||
return;
|
||||
|
||||
pos = pos.floor();
|
||||
size = size.floor();
|
||||
const mgl::vec2i mouse_pos = window.get_mouse_position();
|
||||
const mgl::vec2f webcam_box_min_size = clamp_keep_aspect_ratio(selected_camera->size.to_vec2f(), screen_inner_size * 0.2f);
|
||||
const mgl::vec2f webcam_box_min_size = clamp_keep_aspect_ratio(selected_camera_setup->resolution.to_vec2f(), screen_inner_size * 0.2f);
|
||||
|
||||
if(moving_webcam_box) {
|
||||
webcam_box_pos = mouse_pos.to_vec2f() - screen_border_size - webcam_box_grab_offset - pos;
|
||||
@@ -276,7 +289,7 @@ namespace gsr {
|
||||
webcam_box_size = webcam_box_size_resize_start + mouse_diff;
|
||||
}
|
||||
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera->size.to_vec2f(), webcam_box_size);
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera_setup->resolution.to_vec2f(), webcam_box_size);
|
||||
|
||||
if(webcam_box_pos.x < 0.0f)
|
||||
webcam_box_pos.x = 0.0f;
|
||||
@@ -300,7 +313,7 @@ namespace gsr {
|
||||
else if(webcam_box_pos.y + webcam_box_size.y > screen_inner_size.y)
|
||||
webcam_box_size.y = screen_inner_size.y - webcam_box_pos.y;
|
||||
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera->size.to_vec2f(), webcam_box_size);
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera_setup->resolution.to_vec2f(), webcam_box_size);
|
||||
|
||||
{
|
||||
draw_rectangle_outline(window, pos, size, mgl::Color(255, 0, 0, 255), screen_border);
|
||||
@@ -310,7 +323,7 @@ namespace gsr {
|
||||
}
|
||||
|
||||
{
|
||||
webcam_box_drawn_size = clamp_keep_aspect_ratio(selected_camera->size.to_vec2f(), webcam_box_size);
|
||||
webcam_box_drawn_size = clamp_keep_aspect_ratio(selected_camera_setup->resolution.to_vec2f(), webcam_box_size);
|
||||
webcam_box_drawn_pos = (pos + screen_border_size + webcam_box_pos).floor();
|
||||
|
||||
draw_rectangle_outline(window, webcam_box_drawn_pos, webcam_box_drawn_size, mgl::Color(0, 255, 0, 255), screen_border);
|
||||
@@ -1280,11 +1293,6 @@ namespace gsr {
|
||||
streaming_info_list->add_widget(create_stream_custom_section());
|
||||
|
||||
settings_list_ptr->add_widget(std::make_unique<Subsection>("Streaming info", std::move(streaming_info_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
|
||||
|
||||
auto general_list = std::make_unique<List>(List::Orientation::VERTICAL);
|
||||
general_list->add_widget(create_save_recording_in_game_folder());
|
||||
|
||||
settings_list_ptr->add_widget(std::make_unique<Subsection>("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
|
||||
settings_list_ptr->add_widget(std::make_unique<Subsection>("Streaming indicator", create_indicator("streaming"), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
|
||||
|
||||
streaming_service_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) {
|
||||
@@ -1434,8 +1442,8 @@ namespace gsr {
|
||||
webcam_box_size.x = ((float)record_options.webcam_width / 100.0f * screen_inner_size.x);
|
||||
webcam_box_size.y = ((float)record_options.webcam_height / 100.0f * screen_inner_size.y);
|
||||
|
||||
if(selected_camera.has_value())
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera->size.to_vec2f(), webcam_box_size);
|
||||
if(selected_camera_setup.has_value())
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera_setup->resolution.to_vec2f(), webcam_box_size);
|
||||
|
||||
if(record_options.record_area_width == 0)
|
||||
record_options.record_area_width = 1920;
|
||||
@@ -1569,8 +1577,8 @@ namespace gsr {
|
||||
record_options.show_notifications = show_notification_checkbox_ptr->is_checked();
|
||||
record_options.use_led_indicator = led_indicator_checkbox_ptr->is_checked();
|
||||
|
||||
if(selected_camera.has_value())
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera->size.to_vec2f(), webcam_box_size);
|
||||
if(selected_camera_setup.has_value())
|
||||
webcam_box_size = clamp_keep_aspect_ratio(selected_camera_setup->resolution.to_vec2f(), webcam_box_size);
|
||||
|
||||
record_options.webcam_source = webcam_sources_box_ptr->get_selected_id();
|
||||
record_options.webcam_flip_horizontally = flip_camera_horizontally_checkbox_ptr->is_checked();
|
||||
|
||||
Reference in New Issue
Block a user