From 93d5a8be32be697d57915d1f2bf527a041b5c06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 15 Apr 2024 23:36:20 +0200 Subject: [PATCH 1/2] Improve descriptions of demo-related console commands --- src/engine/client/client.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 86581ee78..369945741 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -4092,18 +4092,18 @@ void CClient::RegisterCommands() m_pConsole->Register("rcon", "r[rcon-command]", CFGFLAG_CLIENT, Con_Rcon, this, "Send specified command to rcon"); m_pConsole->Register("rcon_auth", "r[password]", CFGFLAG_CLIENT, Con_RconAuth, this, "Authenticate to rcon"); m_pConsole->Register("rcon_login", "s[username] r[password]", CFGFLAG_CLIENT, Con_RconLogin, this, "Authenticate to rcon with a username"); - m_pConsole->Register("play", "r[file]", CFGFLAG_CLIENT | CFGFLAG_STORE, Con_Play, this, "Play the file specified"); - m_pConsole->Register("record", "?r[file]", CFGFLAG_CLIENT, Con_Record, this, "Record to the file"); - m_pConsole->Register("stoprecord", "", CFGFLAG_CLIENT, Con_StopRecord, this, "Stop recording"); + m_pConsole->Register("play", "r[file]", CFGFLAG_CLIENT | CFGFLAG_STORE, Con_Play, this, "Play back a demo"); + m_pConsole->Register("record", "?r[file]", CFGFLAG_CLIENT, Con_Record, this, "Start recording a demo"); + m_pConsole->Register("stoprecord", "", CFGFLAG_CLIENT, Con_StopRecord, this, "Stop recording a demo"); m_pConsole->Register("add_demomarker", "", CFGFLAG_CLIENT, Con_AddDemoMarker, this, "Add demo timeline marker"); m_pConsole->Register("begin_favorite_group", "", CFGFLAG_CLIENT, Con_BeginFavoriteGroup, this, "Use this before `add_favorite` to group favorites. End with `end_favorite_group`"); m_pConsole->Register("end_favorite_group", "", CFGFLAG_CLIENT, Con_EndFavoriteGroup, this, "Use this after `add_favorite` to group favorites. Start with `begin_favorite_group`"); m_pConsole->Register("add_favorite", "s[host|ip] ?s['allow_ping']", CFGFLAG_CLIENT, Con_AddFavorite, this, "Add a server as a favorite"); m_pConsole->Register("remove_favorite", "r[host|ip]", CFGFLAG_CLIENT, Con_RemoveFavorite, this, "Remove a server from favorites"); - m_pConsole->Register("demo_slice_start", "", CFGFLAG_CLIENT, Con_DemoSliceBegin, this, "Mark the beginning of a cut"); - m_pConsole->Register("demo_slice_end", "", CFGFLAG_CLIENT, Con_DemoSliceEnd, this, "Mark the end of a cut"); - m_pConsole->Register("demo_play", "", CFGFLAG_CLIENT, Con_DemoPlay, this, "Play demo"); - m_pConsole->Register("demo_speed", "i[speed]", CFGFLAG_CLIENT, Con_DemoSpeed, this, "Set demo speed"); + m_pConsole->Register("demo_slice_start", "", CFGFLAG_CLIENT, Con_DemoSliceBegin, this, "Mark the beginning of a demo cut"); + m_pConsole->Register("demo_slice_end", "", CFGFLAG_CLIENT, Con_DemoSliceEnd, this, "Mark the end of a demo cut"); + m_pConsole->Register("demo_play", "", CFGFLAG_CLIENT, Con_DemoPlay, this, "Play/pause the current demo"); + m_pConsole->Register("demo_speed", "i[speed]", CFGFLAG_CLIENT, Con_DemoSpeed, this, "Set current demo speed"); m_pConsole->Register("save_replay", "?i[length] ?r[filename]", CFGFLAG_CLIENT, Con_SaveReplay, this, "Save a replay of the last defined amount of seconds"); m_pConsole->Register("benchmark_quit", "i[seconds] r[file]", CFGFLAG_CLIENT | CFGFLAG_STORE, Con_BenchmarkQuit, this, "Benchmark frame times for number of seconds to file, then quit"); From d2c8132fb6c4c7ffa9b3689444f6f383fe179c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Mon, 15 Apr 2024 23:39:24 +0200 Subject: [PATCH 2/2] Add optional name argument to `start_video` command, refactoring Add optional filename argument to `start_video` command, to start recording to a video file with a specific filename, instead of always using the current timestamp. Add log messages to `start_video` and `stop_video` commands to indicate success and errors. Make the `CClient::StartVideo` function non-`static` and reduce duplicate code in the `Con_StartVideo` function. Determine the video filename outside of the `CVideo` constructor, same as for demos. --- src/engine/client/client.cpp | 90 ++++++++++++++++++++---------------- src/engine/client/client.h | 2 +- src/engine/client/video.cpp | 10 +--- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 369945741..eee12104e 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -3261,57 +3261,68 @@ void CClient::Con_Screenshot(IConsole::IResult *pResult, void *pUserData) void CClient::Con_StartVideo(IConsole::IResult *pResult, void *pUserData) { - CClient *pSelf = (CClient *)pUserData; + CClient *pSelf = static_cast(pUserData); - if(pSelf->State() != IClient::STATE_DEMOPLAYBACK) + if(pResult->NumArguments()) { - pSelf->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "videorecorder", "Can not start videorecorder outside of demoplayer."); + pSelf->StartVideo(pResult->GetString(0), false); + } + else + { + pSelf->StartVideo("video", true); + } +} + +void CClient::StartVideo(const char *pFilename, bool WithTimestamp) +{ + if(State() != IClient::STATE_DEMOPLAYBACK) + { + log_error("videorecorder", "Video can only be recorded in demo player."); return; } - if(!IVideo::Current()) + if(IVideo::Current()) { - // wait for idle, so there is no data race - pSelf->Graphics()->WaitForIdle(); - // pause the sound device while creating the video instance - pSelf->Sound()->PauseAudioDevice(); - new CVideo((CGraphics_Threaded *)pSelf->m_pGraphics, pSelf->Sound(), pSelf->Storage(), pSelf->Graphics()->ScreenWidth(), pSelf->Graphics()->ScreenHeight(), ""); - pSelf->Sound()->UnpauseAudioDevice(); - IVideo::Current()->Start(); - bool paused = pSelf->m_DemoPlayer.Info()->m_Info.m_Paused; - if(paused) - IVideo::Current()->Pause(true); + log_error("videorecorder", "Already recording."); + return; + } + + char aFilename[IO_MAX_PATH_LENGTH]; + if(WithTimestamp) + { + char aTimestamp[20]; + str_timestamp(aTimestamp, sizeof(aTimestamp)); + str_format(aFilename, sizeof(aFilename), "videos/%s_%s.mp4", pFilename, aTimestamp); } else - pSelf->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "videorecorder", "Videorecorder already running."); -} - -void CClient::StartVideo(IConsole::IResult *pResult, void *pUserData, const char *pVideoName) -{ - CClient *pSelf = (CClient *)pUserData; - - if(pSelf->State() != IClient::STATE_DEMOPLAYBACK) - pSelf->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "videorecorder", "Can not start videorecorder outside of demoplayer."); - - pSelf->m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "demo_render", pVideoName); - if(!IVideo::Current()) { - // wait for idle, so there is no data race - pSelf->Graphics()->WaitForIdle(); - // pause the sound device while creating the video instance - pSelf->Sound()->PauseAudioDevice(); - new CVideo((CGraphics_Threaded *)pSelf->m_pGraphics, pSelf->Sound(), pSelf->Storage(), pSelf->Graphics()->ScreenWidth(), pSelf->Graphics()->ScreenHeight(), pVideoName); - pSelf->Sound()->UnpauseAudioDevice(); - IVideo::Current()->Start(); + str_format(aFilename, sizeof(aFilename), "videos/%s.mp4", pFilename); } - else - pSelf->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "videorecorder", "Videorecorder already running."); + + // wait for idle, so there is no data race + Graphics()->WaitForIdle(); + // pause the sound device while creating the video instance + Sound()->PauseAudioDevice(); + new CVideo((CGraphics_Threaded *)m_pGraphics, Sound(), Storage(), Graphics()->ScreenWidth(), Graphics()->ScreenHeight(), aFilename); + Sound()->UnpauseAudioDevice(); + IVideo::Current()->Start(); + if(m_DemoPlayer.Info()->m_Info.m_Paused) + { + IVideo::Current()->Pause(true); + } + log_info("videorecorder", "Recording to '%s'", aFilename); } void CClient::Con_StopVideo(IConsole::IResult *pResult, void *pUserData) { - if(IVideo::Current()) - IVideo::Current()->Stop(); + if(!IVideo::Current()) + { + log_error("videorecorder", "Not recording."); + return; + } + + IVideo::Current()->Stop(); + log_info("videorecorder", "Stopped recording."); } #endif @@ -3610,8 +3621,7 @@ const char *CClient::DemoPlayer_Render(const char *pFilename, int StorageType, c if(pError) return pError; - this->CClient::StartVideo(NULL, this, pVideoName); - m_DemoPlayer.Play(); + StartVideo(pVideoName, false); m_DemoPlayer.SetSpeedIndex(SpeedIndex); if(StartPaused) { @@ -4085,7 +4095,7 @@ void CClient::RegisterCommands() m_pConsole->Register("screenshot", "", CFGFLAG_CLIENT | CFGFLAG_STORE, Con_Screenshot, this, "Take a screenshot"); #if defined(CONF_VIDEORECORDER) - m_pConsole->Register("start_video", "", CFGFLAG_CLIENT, Con_StartVideo, this, "Start recording a video"); + m_pConsole->Register("start_video", "?r[file]", CFGFLAG_CLIENT, Con_StartVideo, this, "Start recording a video"); m_pConsole->Register("stop_video", "", CFGFLAG_CLIENT, Con_StopVideo, this, "Stop recording a video"); #endif diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 5254e009c..be4ed3553 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -395,7 +395,7 @@ public: static void Con_Screenshot(IConsole::IResult *pResult, void *pUserData); #if defined(CONF_VIDEORECORDER) - static void StartVideo(IConsole::IResult *pResult, void *pUserData, const char *pVideoName); + void StartVideo(const char *pFilename, bool WithTimestamp); static void Con_StartVideo(IConsole::IResult *pResult, void *pUserData); static void Con_StopVideo(IConsole::IResult *pResult, void *pUserData); const char *DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex, bool StartPaused = false) override; diff --git a/src/engine/client/video.cpp b/src/engine/client/video.cpp index 62eeaf859..4dd32c689 100644 --- a/src/engine/client/video.cpp +++ b/src/engine/client/video.cpp @@ -78,16 +78,8 @@ void CVideo::Start() m_AudioStream = {}; m_VideoStream = {}; - char aDate[20]; - str_timestamp(aDate, sizeof(aDate)); - char aBuf[256]; - if(str_length(m_aName) != 0) - str_format(aBuf, sizeof(aBuf), "videos/%s", m_aName); - else - str_format(aBuf, sizeof(aBuf), "videos/%s.mp4", aDate); - char aWholePath[1024]; - IOHANDLE File = m_pStorage->OpenFile(aBuf, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath)); + IOHANDLE File = m_pStorage->OpenFile(m_aName, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath)); if(File) {