Centralize legacy recording bridge

This commit is contained in:
2026-06-04 12:58:27 +02:00
parent 65e9fdf1b9
commit a9ed201adf
9 changed files with 351 additions and 40 deletions

View File

@@ -11,6 +11,7 @@
#include "app_core/document_route.h"
#include "app_core/document_session.h"
#include "legacy_history_services.h"
#include "legacy_recording_services.h"
#include "platform_api/platform_services.h"
#include "renderer_gl/opengl_capabilities.h"
@@ -767,56 +768,30 @@ void App::rec_clear()
rec_running,
platform_deletes_recorded_files_on_clear()
);
if (plan.stop_running_recording)
rec_stop();
if (plan.delete_recorded_files)
clear_platform_recorded_files(rec_path);
rec_count = plan.frame_count_after_clear;
update_rec_frames();
const auto status = pp::panopainter::execute_legacy_recording_clear_plan(*this, plan);
if (!status.ok())
LOG("Recording clear action failed: %s", status.message);
}
void App::rec_start()
{
const auto plan = pp::app::plan_recording_start(rec_running);
switch (plan)
{
case pp::app::RecordingStartAction::start_thread:
break;
case pp::app::RecordingStartAction::no_op_already_running:
return;
}
update_rec_frames();
rec_thread = std::thread(&App::rec_loop, this);
const auto status = pp::panopainter::execute_legacy_recording_start_action(*this, plan);
if (!status.ok())
LOG("Recording start action failed: %s", status.message);
}
void App::rec_stop()
{
const auto plan = pp::app::plan_recording_stop(rec_running);
switch (plan)
{
case pp::app::RecordingStopAction::stop_thread:
break;
case pp::app::RecordingStopAction::no_op_not_running:
return;
}
rec_running = false;
rec_cv.notify_all();
if (rec_thread.joinable())
rec_thread.join();
update_rec_frames();
const auto status = pp::panopainter::execute_legacy_recording_stop_action(*this, plan);
if (!status.ok())
LOG("Recording stop action failed: %s", status.message);
}
void App::rec_export(std::string path)
{
const auto plan = pp::app::plan_recording_export(static_cast<std::size_t>(rec_count));
auto pb = layout[main_id]->add_child<NodeProgressBar>();
pb->m_progress->SetWidthP(0);
pb->m_title->set_text("Exporting MP4 movie");
pb->m_total = plan.progress_total;
pb->m_count = 0;
/*
#if defined(__IOS__) || defined(__OSX__)
export_mp4(rec_path, width, height, rec_count, ^(float) {
@@ -824,9 +799,9 @@ void App::rec_export(std::string path)
});
#endif
*/
Canvas::I->m_encoder->write_mp4(path);
pb->destroy();
const auto status = pp::panopainter::execute_legacy_recording_export_plan(*this, plan, path);
if (!status.ok())
LOG("Recording export action failed: %s", status.message);
}
void App::rec_loop()

View File

@@ -1,7 +1,10 @@
#pragma once
#include "foundation/result.h"
#include <cstddef>
#include <limits>
#include <string_view>
namespace pp::app {
@@ -26,6 +29,20 @@ struct RecordingExportPlan {
int progress_total = 0;
};
class RecordingServices {
public:
virtual ~RecordingServices() = default;
virtual void start_thread() = 0;
virtual void stop_thread() = 0;
virtual void delete_recorded_files() = 0;
virtual void set_frame_count(int frame_count) = 0;
virtual void update_frame_label() = 0;
virtual void begin_export(int progress_total) = 0;
virtual void write_mp4(std::string_view path) = 0;
virtual void end_export() = 0;
};
[[nodiscard]] constexpr RecordingStartAction plan_recording_start(bool is_running) noexcept
{
return is_running
@@ -60,4 +77,60 @@ struct RecordingExportPlan {
};
}
[[nodiscard]] inline pp::foundation::Status execute_recording_start_action(
RecordingStartAction action,
RecordingServices& services)
{
switch (action) {
case RecordingStartAction::start_thread:
services.start_thread();
return pp::foundation::Status::success();
case RecordingStartAction::no_op_already_running:
return pp::foundation::Status::success();
}
return pp::foundation::Status::invalid_argument("unknown recording start action");
}
[[nodiscard]] inline pp::foundation::Status execute_recording_stop_action(
RecordingStopAction action,
RecordingServices& services)
{
switch (action) {
case RecordingStopAction::stop_thread:
services.stop_thread();
return pp::foundation::Status::success();
case RecordingStopAction::no_op_not_running:
return pp::foundation::Status::success();
}
return pp::foundation::Status::invalid_argument("unknown recording stop action");
}
[[nodiscard]] inline pp::foundation::Status execute_recording_clear_plan(
const RecordingClearPlan& plan,
RecordingServices& services)
{
if (plan.stop_running_recording) {
services.stop_thread();
}
if (plan.delete_recorded_files) {
services.delete_recorded_files();
}
services.set_frame_count(plan.frame_count_after_clear);
services.update_frame_label();
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Status execute_recording_export_plan(
const RecordingExportPlan& plan,
RecordingServices& services,
std::string_view path)
{
services.begin_export(plan.progress_total);
services.write_mp4(path);
services.end_export();
return pp::foundation::Status::success();
}
}

View File

@@ -0,0 +1,110 @@
#include "pch.h"
#include "legacy_recording_services.h"
#include "app.h"
#include "canvas.h"
#include "node_progress_bar.h"
namespace pp::panopainter {
namespace {
class LegacyRecordingServices final : public pp::app::RecordingServices {
public:
explicit LegacyRecordingServices(App& app) noexcept
: app_(app)
{
}
void start_thread() override
{
app_.update_rec_frames();
app_.rec_thread = std::thread(&App::rec_loop, &app_);
}
void stop_thread() override
{
app_.rec_running = false;
app_.rec_cv.notify_all();
if (app_.rec_thread.joinable())
app_.rec_thread.join();
app_.update_rec_frames();
}
void delete_recorded_files() override
{
app_.clear_platform_recorded_files(app_.rec_path);
}
void set_frame_count(int frame_count) override
{
app_.rec_count = frame_count;
}
void update_frame_label() override
{
app_.update_rec_frames();
}
void begin_export(int progress_total) override
{
progress_ = app_.layout[app_.main_id]->add_child<NodeProgressBar>();
progress_->m_progress->SetWidthP(0);
progress_->m_title->set_text("Exporting MP4 movie");
progress_->m_total = progress_total;
progress_->m_count = 0;
}
void write_mp4(std::string_view path) override
{
Canvas::I->m_encoder->write_mp4(std::string(path));
}
void end_export() override
{
if (progress_)
progress_->destroy();
progress_ = nullptr;
}
private:
App& app_;
NodeProgressBar* progress_ = nullptr;
};
} // namespace
pp::foundation::Status execute_legacy_recording_start_action(
App& app,
pp::app::RecordingStartAction action)
{
LegacyRecordingServices services(app);
return pp::app::execute_recording_start_action(action, services);
}
pp::foundation::Status execute_legacy_recording_stop_action(
App& app,
pp::app::RecordingStopAction action)
{
LegacyRecordingServices services(app);
return pp::app::execute_recording_stop_action(action, services);
}
pp::foundation::Status execute_legacy_recording_clear_plan(
App& app,
const pp::app::RecordingClearPlan& plan)
{
LegacyRecordingServices services(app);
return pp::app::execute_recording_clear_plan(plan, services);
}
pp::foundation::Status execute_legacy_recording_export_plan(
App& app,
const pp::app::RecordingExportPlan& plan,
std::string_view path)
{
LegacyRecordingServices services(app);
return pp::app::execute_recording_export_plan(plan, services, path);
}
} // namespace pp::panopainter

View File

@@ -0,0 +1,26 @@
#pragma once
#include "app_core/document_recording.h"
#include "foundation/result.h"
#include <string_view>
class App;
namespace pp::panopainter {
[[nodiscard]] pp::foundation::Status execute_legacy_recording_start_action(
App& app,
pp::app::RecordingStartAction action);
[[nodiscard]] pp::foundation::Status execute_legacy_recording_stop_action(
App& app,
pp::app::RecordingStopAction action);
[[nodiscard]] pp::foundation::Status execute_legacy_recording_clear_plan(
App& app,
const pp::app::RecordingClearPlan& plan);
[[nodiscard]] pp::foundation::Status execute_legacy_recording_export_plan(
App& app,
const pp::app::RecordingExportPlan& plan,
std::string_view path);
} // namespace pp::panopainter