#include "pch.h" #include "legacy_recording_services.h" #include "app.h" #include "canvas.h" #include "app_core/app_status.h" #include "legacy_app_dialog_services.h" #include "legacy_ui_overlay_services.h" #include "node_progress_bar.h" namespace pp::panopainter { void update_legacy_recording_frame_label(App& app); namespace { pp::app::RecordingWorkerIterationPlan make_recording_worker_iteration_plan(App& app) { auto* legacy_canvas = Canvas::I; auto* canvas_document = app.canvas ? app.canvas->m_canvas.get() : nullptr; auto* encoder = legacy_canvas ? legacy_canvas->m_encoder.get() : nullptr; return pp::app::plan_recording_worker_iteration( app.rec_running, encoder != nullptr, legacy_canvas != nullptr && canvas_document != nullptr); } void encode_recording_frame( App& app, const pp::app::RecordingWorkerIterationPlan& plan, Canvas* legacy_canvas, Canvas* canvas_document, CanvasEncoder* encoder) { if (plan.clear_dirty_stroke) canvas_document->m_dirty_stroke = false; PBO equirect = legacy_canvas->m_layers_merge.gen_equirect_pbo(encoder->frame_size()); std::this_thread::yield(); ImageRef img; img.create(equirect.width, equirect.height, equirect.map()); encoder->encode(img); equirect.unmap(); LOG("rec frame encoded"); if (plan.update_frame_label) update_legacy_recording_frame_label(app); } } // namespace void update_legacy_recording_frame_label(App& app) { if (auto txt = app.layout[app.main_id]->find("txt-rec")) { const auto label = pp::app::make_recording_frame_label( app.rec_running, Canvas::I->m_encoder != nullptr, Canvas::I->m_encoder ? Canvas::I->m_encoder->frames_count() : 0); txt->set_text(label.text.c_str()); } } namespace { class LegacyRecordingServices final : public pp::app::RecordingServices { public: explicit LegacyRecordingServices(App& app) noexcept : app_(app) { } void start_thread() override { update_legacy_recording_frame_label(app_); app_.rec_thread = std::jthread(&App::rec_loop, &app_); } void stop_thread() override { app_.rec_thread.request_stop(); app_.rec_running = false; app_.rec_cv.notify_all(); if (app_.rec_thread.joinable()) app_.rec_thread.join(); update_legacy_recording_frame_label(app_); } 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 { update_legacy_recording_frame_label(app_); } void begin_export(int progress_total) override { pp::app::RecordingExportPlan plan; plan.progress_total = progress_total; progress_ = pp::panopainter::create_legacy_app_progress_dialog( app_, pp::app::plan_recording_export_progress_dialog(plan)).get(); } void write_mp4(std::string_view path) override { Canvas::I->m_encoder->write_mp4(std::string(path)); } void end_export() override { if (progress_) pp::panopainter::close_legacy_dialog_node(*progress_); progress_ = nullptr; } private: App& app_; NodeProgressBar* progress_ = nullptr; }; } // namespace bool process_legacy_recording_worker_iteration(App& app) { std::unique_lock lock(app.rec_mutex); app.rec_cv.wait(lock); const auto plan = make_recording_worker_iteration_plan(app); if (!plan.continue_running) return false; auto* legacy_canvas = Canvas::I; auto* canvas_document = app.canvas ? app.canvas->m_canvas.get() : nullptr; auto* encoder = legacy_canvas ? legacy_canvas->m_encoder.get() : nullptr; if (plan.encode_frame && legacy_canvas && canvas_document && encoder) encode_recording_frame(app, plan, legacy_canvas, canvas_document, encoder); return true; } 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