165 lines
4.5 KiB
C++
165 lines
4.5 KiB
C++
#pragma once
|
|
|
|
#include "app_core/app_dialog.h"
|
|
#include "foundation/result.h"
|
|
|
|
#include <cstddef>
|
|
#include <limits>
|
|
#include <string_view>
|
|
|
|
namespace pp::app {
|
|
|
|
enum class RecordingStartAction {
|
|
start_thread,
|
|
no_op_already_running,
|
|
};
|
|
|
|
enum class RecordingStopAction {
|
|
stop_thread,
|
|
no_op_not_running,
|
|
};
|
|
|
|
struct RecordingClearPlan {
|
|
bool stop_running_recording = false;
|
|
bool delete_recorded_files = false;
|
|
int frame_count_after_clear = 0;
|
|
};
|
|
|
|
struct RecordingExportPlan {
|
|
std::size_t frame_count = 0;
|
|
int progress_total = 0;
|
|
};
|
|
|
|
struct RecordingWorkerIterationPlan {
|
|
bool continue_running = true;
|
|
bool encode_frame = false;
|
|
bool clear_dirty_stroke = false;
|
|
bool update_frame_label = false;
|
|
};
|
|
|
|
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
|
|
? RecordingStartAction::no_op_already_running
|
|
: RecordingStartAction::start_thread;
|
|
}
|
|
|
|
[[nodiscard]] constexpr RecordingStopAction plan_recording_stop(bool is_running) noexcept
|
|
{
|
|
return is_running
|
|
? RecordingStopAction::stop_thread
|
|
: RecordingStopAction::no_op_not_running;
|
|
}
|
|
|
|
[[nodiscard]] constexpr RecordingClearPlan plan_recording_clear(
|
|
bool is_running,
|
|
bool platform_deletes_recorded_files) noexcept
|
|
{
|
|
return {
|
|
is_running,
|
|
platform_deletes_recorded_files,
|
|
0,
|
|
};
|
|
}
|
|
|
|
[[nodiscard]] constexpr RecordingExportPlan plan_recording_export(std::size_t frame_count) noexcept
|
|
{
|
|
const auto max_progress_total = static_cast<std::size_t>(std::numeric_limits<int>::max());
|
|
return {
|
|
frame_count,
|
|
frame_count > max_progress_total ? std::numeric_limits<int>::max() : static_cast<int>(frame_count),
|
|
};
|
|
}
|
|
|
|
[[nodiscard]] inline AppProgressDialogPlan plan_recording_export_progress_dialog(
|
|
const RecordingExportPlan& plan)
|
|
{
|
|
return plan_app_progress_dialog("Exporting MP4 movie", plan.progress_total);
|
|
}
|
|
|
|
[[nodiscard]] constexpr RecordingWorkerIterationPlan plan_recording_worker_iteration(
|
|
bool is_running_after_wake,
|
|
bool has_encoder,
|
|
bool has_canvas_document) noexcept
|
|
{
|
|
const bool encode = is_running_after_wake && has_encoder && has_canvas_document;
|
|
return {
|
|
.continue_running = is_running_after_wake,
|
|
.encode_frame = encode,
|
|
.clear_dirty_stroke = encode,
|
|
.update_frame_label = encode,
|
|
};
|
|
}
|
|
|
|
[[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();
|
|
}
|
|
|
|
}
|