Implemented delayed start of recording

This commit is contained in:
Bruno
2021-05-13 22:15:50 +02:00
parent 9c8d1f31f6
commit e892dc1eb5
5 changed files with 97 additions and 55 deletions

View File

@@ -311,11 +311,9 @@ View::Cursor LayerView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair
// apply change
float d = setDepth( s, MAX( -dest_translation.x, 0.f) );
// store action in history
std::ostringstream info;
info << "Depth " << std::fixed << std::setprecision(2) << d << " ";
// info << (s->locked() ? ICON_FA_LOCK : ICON_FA_LOCK_OPEN); // TODO static not locked
// store action in history
current_action_ = s->name() + ": " + info.str();
return Cursor(Cursor_ResizeNESW, info.str() );

View File

@@ -99,6 +99,7 @@ void Settings::Save()
RecordNode->SetAttribute("path", application.record.path.c_str());
RecordNode->SetAttribute("profile", application.record.profile);
RecordNode->SetAttribute("timeout", application.record.timeout);
RecordNode->SetAttribute("delay", application.record.delay);
pRoot->InsertEndChild(RecordNode);
// Transition
@@ -293,6 +294,7 @@ void Settings::Load()
if (recordnode != nullptr) {
recordnode->QueryIntAttribute("profile", &application.record.profile);
recordnode->QueryFloatAttribute("timeout", &application.record.timeout);
recordnode->QueryIntAttribute("delay", &application.record.delay);
const char *path_ = recordnode->Attribute("path");
if (path_)

View File

@@ -69,10 +69,12 @@ struct RecordConfig
std::string path;
int profile;
float timeout;
int delay;
RecordConfig() : path("") {
profile = 0;
timeout = RECORD_MAX_TIMEOUT;
delay = 0;
}
};

View File

@@ -89,6 +89,12 @@ static std::vector< std::future<std::string> > fileImportFileDialogs;
static std::vector< std::future<std::string> > recentFolderFileDialogs;
static std::vector< std::future<std::string> > recordFolderFileDialogs;
static std::vector< std::future<FrameGrabber *> > _video_recorders;
FrameGrabber *delayTrigger(FrameGrabber *g, std::chrono::milliseconds delay) {
std::this_thread::sleep_for (delay);
return g;
}
UserInterface::UserInterface()
{
@@ -105,8 +111,8 @@ UserInterface::UserInterface()
screenshot_step = 0;
// keep hold on frame grabbers
video_recorder_ = 0;
webcam_emulator_ = 0;
video_recorder_ = nullptr;
webcam_emulator_ = nullptr;
}
bool UserInterface::Init()
@@ -246,16 +252,18 @@ void UserInterface::handleKeyboard()
Mixer::manager().view()->selectAll();
}
else if (ImGui::IsKeyPressed( GLFW_KEY_R )) {
// toggle recording
FrameGrabber *rec = FrameGrabbing::manager().get(video_recorder_);
if (rec) {
rec->stop();
video_recorder_ = 0;
if (shift_modifier_active) {
FrameGrabbing::manager().add(new PNGRecorder);
}
else {
FrameGrabber *fg = new VideoRecorder;
video_recorder_ = fg->id();
FrameGrabbing::manager().add(fg);
// toggle recording
if (video_recorder_) {
video_recorder_->stop();
video_recorder_ = nullptr;
}
else {
_video_recorders.emplace_back( std::async(std::launch::async, delayTrigger, new VideoRecorder, std::chrono::seconds(Settings::application.record.delay)) );
}
}
}
else if (ImGui::IsKeyPressed( GLFW_KEY_Y )) {
@@ -749,11 +757,21 @@ void UserInterface::Render()
&Settings::application.widget.stats_corner,
&Settings::application.widget.stats_mode);
// management of video_recorder
FrameGrabber *rec = FrameGrabbing::manager().get(video_recorder_);
if (rec && rec->duration() > Settings::application.record.timeout ){
rec->stop();
video_recorder_ = 0;
// management of video_recorders
if ( !_video_recorders.empty() ) {
// check that file dialog thread finished
if (_video_recorders.back().wait_for(timeout) == std::future_status::ready ) {
video_recorder_ = _video_recorders.back().get();
FrameGrabbing::manager().add(video_recorder_);
_video_recorders.pop_back();
}
}
if (video_recorder_ && video_recorder_->duration() > Settings::application.record.timeout ){
video_recorder_->stop();
video_recorder_ = nullptr;
}
// all IMGUI Rendering
@@ -996,10 +1014,6 @@ void UserInterface::RenderPreview()
preview_window_pos = ImGui::GetWindowPos();
preview_window_size = ImGui::GetWindowSize();
FrameGrabber *rec = FrameGrabbing::manager().get(video_recorder_);
#if defined(LINUX)
FrameGrabber *cam = FrameGrabbing::manager().get(webcam_emulator_);
#endif
// return from thread for folder openning
if ( !recordFolderFileDialogs.empty() ) {
// check that file dialog thread finished
@@ -1026,7 +1040,7 @@ void UserInterface::RenderPreview()
info << " " << FrameBuffer::aspect_ratio_name[p.x] ;
ImGui::MenuItem(info.str().c_str(), nullptr, false, false);
// cannot change resolution when recording
if (rec == nullptr && p.y > -1) {
if (video_recorder_ == nullptr && p.y > -1) {
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Height", &p.y, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) ) )
{
@@ -1049,36 +1063,47 @@ void UserInterface::RenderPreview()
}
if (ImGui::BeginMenu("Record"))
{
if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Capture frame (PNG)") )
if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Capture frame (PNG)", CTRL_MOD "Shitf+R") )
FrameGrabbing::manager().add(new PNGRecorder);
// Stop recording menu if main recorder already exists
if (rec) {
if (!_video_recorders.empty()) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.8f));
ImGui::MenuItem( ICON_FA_SQUARE " Record starting", CTRL_MOD "R", false, false);
ImGui::PopStyleColor(1);
static char dummy_str[512];
sprintf(dummy_str, "%s", VideoRecorder::profile_name[Settings::application.record.profile]);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.5f));
ImGui::InputText("Codec", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
ImGui::PopStyleColor(1);
}
else if (video_recorder_) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.8f));
if ( ImGui::MenuItem( ICON_FA_SQUARE " Stop Record", CTRL_MOD "R") ) {
rec->stop();
video_recorder_ = 0;
video_recorder_->stop();
video_recorder_ = nullptr;
}
ImGui::PopStyleColor(1);
static char dummy_str[512];
sprintf(dummy_str, "%s", VideoRecorder::profile_name[Settings::application.record.profile]);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.5f));
ImGui::InputText("Codec", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
ImGui::PopStyleColor(1);
}
// start recording
else {
// detecting the absence of video recorder but the variable is still not 0: fix this!
if (video_recorder_ > 0)
video_recorder_ = 0;
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.9f));
if ( ImGui::MenuItem( ICON_FA_CIRCLE " Record", CTRL_MOD "R") ) {
FrameGrabber *fg = new VideoRecorder;
video_recorder_ = fg->id();
FrameGrabbing::manager().add(fg);
_video_recorders.emplace_back( std::async(std::launch::async, delayTrigger, new VideoRecorder, std::chrono::seconds(Settings::application.record.delay)) );
}
ImGui::PopStyleColor(1);
// select profile
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("Codec", &Settings::application.record.profile, VideoRecorder::profile_name, IM_ARRAYSIZE(VideoRecorder::profile_name) );
}
// Options menu
ImGui::Separator();
ImGui::MenuItem("Options", nullptr, false, false);
@@ -1110,31 +1135,30 @@ void UserInterface::RenderPreview()
Settings::application.record.path = SystemToolkit::home_path();
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::SliderFloat("Timeout", &Settings::application.record.timeout, 1.f, RECORD_MAX_TIMEOUT,
Settings::application.record.timeout < (RECORD_MAX_TIMEOUT - 1.f) ? "%.0f s" : "None", 3.f);
ImGui::SliderFloat("Duration", &Settings::application.record.timeout, 1.f, RECORD_MAX_TIMEOUT,
Settings::application.record.timeout < (RECORD_MAX_TIMEOUT - 1.f) ? "%.0f s" : "Until stopped", 3.f);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::SliderInt("Trigger", &Settings::application.record.delay, 0, 5,
Settings::application.record.delay < 1 ? "Immediate" : "After %d s");
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Share stream"))
{
#if defined(LINUX)
bool on = cam != nullptr;
bool on = webcam_emulator_ != nullptr;
if ( ImGui::MenuItem( ICON_FA_CAMERA " Emulate video camera", NULL, &on) ) {
if (on && cam == nullptr) {
if (webcam_emulator_ > 0)
webcam_emulator_ = 0;
if (on) {
if (Loopback::systemLoopbackInitialized()) {
FrameGrabber *fg = new Loopback;
webcam_emulator_ = fg->id();
FrameGrabbing::manager().add(fg);
webcam_emulator_ = new Loopback;
FrameGrabbing::manager().add(webcam_emulator_);
}
else
openInitializeSystemLoopback = true;
}
if (!on && cam != nullptr) {
cam->stop();
webcam_emulator_ = 0;
else {
webcam_emulator_->stop();
webcam_emulator_ = nullptr;
}
}
#endif
@@ -1179,13 +1203,25 @@ void UserInterface::RenderPreview()
ImGui::Text(" %d x %d px, %.d fps", output->width(), output->height(), int(Mixer::manager().fps()) );
}
// recording indicator overlay
if (rec)
if (video_recorder_)
{
float r = ImGui::GetTextLineHeightWithSpacing();
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + r, draw_pos.y + r));
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.8f));
ImGui::Text(ICON_FA_CIRCLE " %s", rec->info().c_str() );
ImGui::Text(ICON_FA_CIRCLE " %s", video_recorder_->info().c_str() );
ImGui::PopStyleColor(1);
ImGui::PopFont();
}
else if (!_video_recorders.empty())
{
float r = ImGui::GetTextLineHeightWithSpacing();
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + r, draw_pos.y + r));
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
static double anim = 0.f;
double a = sin(anim+=0.104); // 2 * pi / 60fps
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, a));
ImGui::Text(ICON_FA_CIRCLE);
ImGui::PopStyleColor(1);
ImGui::PopFont();
}
@@ -1220,7 +1256,7 @@ void UserInterface::RenderPreview()
static char dummy_str[512];
sprintf(dummy_str, "sudo apt install v4l2loopback-dkms");
ImGui::Text("Install v4l2loopack:");
ImGui::Text("Install v4l2loopack (once):");
ImGui::SetNextItemWidth(600-40);
ImGui::InputText("##cmd1", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
ImGui::SameLine();
@@ -1230,7 +1266,7 @@ void UserInterface::RenderPreview()
ImGui::PopID();
sprintf(dummy_str, "sudo modprobe v4l2loopback exclusive_caps=1 video_nr=10 card_label=\"vimix loopback\"");
ImGui::Text("Initialize v4l2loopack:");
ImGui::Text("Initialize v4l2loopack (after reboot):");
ImGui::SetNextItemWidth(600-40);
ImGui::InputText("##cmd2", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
ImGui::SameLine();
@@ -1241,7 +1277,7 @@ void UserInterface::RenderPreview()
ImGui::Separator();
ImGui::SetItemDefaultFocus();
if (ImGui::Button("Thank you, I'll do this and try again later.", ImVec2(w, 0)) ) {
if (ImGui::Button("Ok, I'll do this in a terminal and try again later.", ImVec2(w, 0)) ) {
ImGui::CloseCurrentPopup();
}

View File

@@ -14,6 +14,7 @@ struct ImVec2;
class Source;
class MediaPlayer;
class FrameBufferImage;
class FrameGrabber;
class SourcePreview {
@@ -138,8 +139,11 @@ class UserInterface
unsigned int screenshot_step;
// frame grabbers
uint64_t video_recorder_;
uint64_t webcam_emulator_;
FrameGrabber *video_recorder_;
#if defined(LINUX)
FrameGrabber *webcam_emulator_;
#endif
// Private Constructor
UserInterface();