28namespace fs = std::filesystem;
34 bool require_portal(
const char* caller)
38 "{}: Portal::System not initialized", caller);
44 const std::vector<Portal::System::Dialog::ChooserFilter> k_audio_open_filters {
45 { .name =
"Audio", .extensions = {
"wav",
"aiff",
"aif",
"flac",
"ogg",
"mp3",
"m4a",
"wma" } },
46 { .name =
"All Files", .extensions = {
"*" } }
49 const std::vector<Portal::System::Dialog::ChooserFilter> k_audio_save_filters {
50 { .name =
"Audio", .extensions = {
"wav",
"flac",
"ogg",
"mp3" } },
51 { .name =
"All Files", .extensions = {
"*" } }
54 const std::vector<Portal::System::Dialog::ChooserFilter> k_video_filters {
55 { .name =
"Video", .extensions = {
"mp4",
"mkv",
"mov",
"webm",
"avi" } },
56 { .name =
"All Files", .extensions = {
"*" } }
59 const std::vector<Portal::System::Dialog::ChooserFilter> k_image_filters {
60 { .name =
"Image", .extensions = {
"png",
"jpg",
"jpeg",
"bmp",
"tga",
"psd",
"gif",
"hdr",
"pic",
"pnm",
"exr" } },
61 { .name =
"All Files", .extensions = {
"*" } }
64 const std::vector<Portal::System::Dialog::ChooserFilter> k_composite_filters {
65 { .name =
"Composite data", .extensions = {
"csv",
"tsv" } },
66 { .name =
"All Files", .extensions = {
"*" } }
69 const std::vector<Portal::System::Dialog::ChooserFilter> k_mesh_filters {
70 { .name =
"3D Model", .extensions = {
"glb",
"gltf",
"fbx",
"obj",
"ply",
"stl",
"dae" } },
71 { .name =
"All Files", .extensions = {
"*" } }
74 const std::vector<Portal::System::Dialog::ChooserFilter> k_image_save_filters {
75 { .name =
"Image", .extensions = {
"png",
"jpg",
"jpeg",
"bmp",
"tga",
"exr",
"hdr" } },
76 { .name =
"All Files", .extensions = {
"*" } }
79 const std::vector<Portal::System::Dialog::ChooserFilter> k_mesh_save_filters {
80 { .name =
"3D Model", .extensions = {
"gltf",
"glb",
"obj",
"fbx",
"ply",
"stl",
"dae",
"3ds",
"x3d" } },
81 { .name =
"All Files", .extensions = {
"*" } }
84 const std::vector<Portal::System::Dialog::ChooserFilter> k_volume_filters {
85 { .name =
"Volume", .extensions = {
"vdb" } },
86 { .name =
"All Files", .extensions = {
"*" } }
89 const std::vector<Portal::System::Dialog::ChooserFilter> k_spatial_filters {
90 { .name =
"Alembic", .extensions = {
"abc" } },
91 { .name =
"All Files", .extensions = {
"*" } }
96 if (!fs::exists(filepath) || !fs::is_regular_file(filepath))
99 auto ext = filepath.extension().string();
103 std::ranges::transform(ext, ext.begin(), [](
unsigned char c) { return std::tolower(c); });
104 const std::string_view bare { ext.data() + 1, ext.size() - 1 };
106 return std::ranges::any_of(filter.extensions,
107 [&](
const std::string& e) { return e == bare; });
115 const std::shared_ptr<Kakshya::SoundFileContainer>& container)
119 "prepare_audio_buffers failed: null container");
123 uint32_t num_channels = container->get_num_channels();
124 std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> created_buffers;
126 for (uint32_t ch = 0; ch < num_channels; ++ch) {
127 auto buf = std::make_shared<Buffers::SoundContainerBuffer>(
130 created_buffers.push_back(std::move(buf));
133 return created_buffers;
138 return check_extension(filepath, k_image_filters[0]);
143 return check_extension(filepath, k_audio_open_filters[0]);
148 return check_extension(filepath, k_composite_filters[0]);
152 const std::shared_ptr<Kakshya::VideoStreamContainer>& container)
155 if (!io || !container) {
159 if (
const auto camera = std::dynamic_pointer_cast<Kakshya::CameraContainer>(container)) {
160 return io->get_camera_buffer(camera);
163 return io->get_video_buffer(container);
167 const std::shared_ptr<Kakshya::SoundFileContainer>& container)
170 if (!io || !container) {
174 return io->get_audio_buffers(container);
178 const std::shared_ptr<Kakshya::VideoFileContainer>& container)
181 if (!io || !container) {
185 const auto audio = io->get_extracted_audio(container);
186 return audio ? io->get_audio_buffers(audio) : std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> {};
195 if (!require_portal(
"choose_audio"))
198 return Portal::System::Dialog::open_file<std::shared_ptr<Kakshya::SoundFileContainer>>(
199 [](
const fs::path& p) {
return get_io_manager()->load_audio(p.string()); },
201 k_audio_open_filters);
206 if (!require_portal(
"choose_audio_bounded"))
209 return Portal::System::Dialog::open_file<std::shared_ptr<Kakshya::DynamicSoundStream>>(
210 [max_frames, truncate](
const fs::path& p) {
211 return get_io_manager()->load_audio_bounded(p.string(), max_frames, truncate);
214 k_audio_open_filters);
219 if (!require_portal(
"choose_video"))
222 return Portal::System::Dialog::open_file<IO::VideoLoadResult>(
223 [config](
const fs::path& p) {
return get_io_manager()->load_video(p.string(), config); },
229 int desired_channels, std::optional<Kakshya::Region> region)
231 if (!require_portal(
"choose_image"))
234 return Portal::System::Dialog::open_file<std::shared_ptr<Buffers::TextureBuffer>>(
235 [desired_channels, region = std::move(region)](
const fs::path& p) {
236 return get_io_manager()->load_image(p.string(), desired_channels, region);
244 if (!require_portal(
"choose_composite"))
247 return Portal::System::Dialog::open_file<std::shared_ptr<Kakshya::CompositeContainer>>(
248 [](
const fs::path& p) {
return get_io_manager()->load_composite(p.string()); },
250 k_composite_filters);
256 if (!require_portal(
"choose_composite"))
259 return Portal::System::Dialog::open_file<std::shared_ptr<Kakshya::CompositeContainer>>(
260 [&layout, batch_size](
const fs::path& p) {
261 return get_io_manager()->load_composite(p.string(), layout, batch_size);
264 k_composite_filters);
269 if (!require_portal(
"choose_mesh"))
272 return Portal::System::Dialog::open_file<std::vector<std::shared_ptr<Buffers::MeshBuffer>>>(
273 [](
const fs::path& p) {
return get_io_manager()->load_mesh(p.string()); },
280 if (!require_portal(
"choose_mesh_network"))
283 return Portal::System::Dialog::open_file<std::shared_ptr<Nodes::Network::MeshNetwork>>(
284 [r = std::move(resolver)](
const fs::path& p)
mutable {
285 return get_io_manager()->load_mesh_network(p.string(), std::move(r));
293 if (!require_portal(
"choose_volume"))
296 return Portal::System::Dialog::open_file<std::shared_ptr<Buffers::VolumeGridBuffer>>(
297 [](
const fs::path& p) {
return get_io_manager()->load_volume(p.string()); },
304 auto promise = std::make_shared<std::promise<std::shared_ptr<Kakshya::CameraContainer>>>();
305 auto future = promise->get_future();
309 if (configs.empty()) {
311 "choose_camera: no cameras found");
319 [promise, choose_mode, modes = reader.
preset_modes()](std::optional<IO::CameraConfig> camera) {
321 promise->set_value(
nullptr);
330 [promise, config = *camera](std::optional<IO::CameraMode>
mode)
mutable {
332 promise->set_value(
nullptr);
348 const std::shared_ptr<Kakshya::SoundStreamContainer>& container,
349 const std::string& suggested_name)
351 if (!require_portal(
"save_audio"))
357 "save_audio: IOManager unavailable");
361 return Portal::System::Dialog::save_file<bool>(
362 [&iom, &container](
const fs::path& p) {
363 iom->write(container, p.string());
368 k_audio_save_filters);
372 const std::shared_ptr<Buffers::TextureBuffer>&
buffer,
373 const std::string& suggested_name)
375 if (!require_portal(
"save_image"))
381 "save_image: IOManager unavailable");
385 return Portal::System::Dialog::save_file<bool>(
386 [&iom, &
buffer](
const fs::path& p) {
391 k_image_save_filters);
395 const std::shared_ptr<Buffers::TextureBuffer>&
buffer,
396 const std::string& suggested_name,
399 if (!require_portal(
"save_image"))
405 "save_image: IOManager unavailable");
409 return Portal::System::Dialog::save_file<bool>(
410 [&iom, &
buffer, &options](
const fs::path& p) {
411 return iom->save_image(
buffer, p.string(), options);
415 k_image_save_filters);
419 const std::shared_ptr<Kakshya::CompositeContainer>& container,
420 const std::string& suggested_name)
422 if (!require_portal(
"save_composite"))
428 "save_composite: IOManager unavailable");
432 return Portal::System::Dialog::save_file<bool>(
433 [&iom, &container](
const fs::path& p) {
434 return iom->save_composite(container, p.string());
438 k_composite_filters);
442 const std::shared_ptr<Buffers::MeshBuffer>&
buffer,
443 const std::string& suggested_name)
449 const std::shared_ptr<Buffers::MeshBuffer>&
buffer,
450 const std::string& suggested_name,
453 if (!require_portal(
"save_mesh"))
459 "save_mesh: IOManager unavailable");
463 return Portal::System::Dialog::save_file<bool>(
464 [&iom, &
buffer, &options](
const fs::path& p) {
465 return iom->save_mesh(
buffer, p.string(), options);
469 k_mesh_save_filters);
473 const std::shared_ptr<Nodes::Network::MeshNetwork>&
network,
474 const std::string& suggested_name)
480 const std::shared_ptr<Nodes::Network::MeshNetwork>&
network,
481 const std::string& suggested_name,
484 if (!require_portal(
"save_mesh"))
490 "save_mesh: IOManager unavailable");
494 return Portal::System::Dialog::save_file<bool>(
495 [&iom, &
network, &options](
const fs::path& p) {
496 return iom->save_mesh(
network, p.string(), options);
500 k_mesh_save_filters);
504 const std::shared_ptr<Buffers::VolumeGridBuffer>& volume,
505 const std::string& suggested_name)
507 if (!require_portal(
"save_volume"))
513 "save_volume: IOManager unavailable");
517 return Portal::System::Dialog::save_file<bool>(
518 [&iom, &volume](
const fs::path& p) {
527 const std::shared_ptr<Buffers::VolumeGridBuffer>& volume,
528 const std::string& suggested_name,
531 if (!require_portal(
"save_volume"))
537 "save_volume: IOManager unavailable");
541 return Portal::System::Dialog::save_file<bool>(
542 [&iom, &volume, &options](
const fs::path& p) {
543 return iom->save_volume(volume, p.string(), options);
551 std::vector<IO::SpatialCaptureSource> sources,
552 const std::string& suggested_name)
554 if (!require_portal(
"save_spatial"))
560 "save_spatial: IOManager unavailable");
564 return Portal::System::Dialog::save_file<bool>(
565 [&iom, &sources](
const fs::path& p) {
566 return iom->save_spatial_snapshot(std::move(sources), p.string());
581 "Attempted to access IOManager before engine initialization");
#define MF_ERROR(comp, ctx,...)
Core::GlobalNetworkConfig network
Core engine lifecycle and configuration API.
Dialog-backed loading and file-type helpers.
std::shared_ptr< NetworkGeometryBuffer > buffer
std::shared_ptr< IO::IOManager > get_io_manager()
Gets the IO manager.
std::vector< CameraMode > preset_modes() const override
Capture modes this source offers as defaults, ordered from safest to most demanding.
std::vector< CameraConfig > enumerate_configs() const override
Discover ready-to-open camera configurations without starting capture.
Platform-specific FFmpeg input format string for camera devices.
Shared field description and byte layout for a CompositeArray.
uint32_t get_buffer_size()
Gets the buffer size from the default engine.
SystemDialogError
Failure modes for OS dialog operations.
std::pair< std::shared_ptr< Kakshya::VideoFileContainer >, std::shared_ptr< Kakshya::SoundFileContainer > > VideoLoadResult
Result of load_video(path, config): the video container, then its audio.
std::function< std::shared_ptr< Core::VKImage >(const std::string &)> TextureResolver
Callable that maps a raw material texture path to a GPU image.
@ Runtime
General runtime operations (default fallback)
@ API
MayaFlux/API Wrapper and convenience functions.
T await_future(std::future< T > future)
Core::SystemFileFilter ChooserFilter
A named group of accepted file extensions.
bool is_initialized()
Return true if Portal::System has been initialized.
bool is_engine_configured()
Checks if the default engine has currently accepted all configurations and initialized all managers.
std::shared_ptr< Buffers::TextureBuffer > choose_image(int desired_channels, std::optional< Kakshya::Region > region)
Present a native open-file dialog filtered to image formats and load the chosen file via IOManager::l...
bool is_image(const fs::path &filepath)
bool save_volume(const std::shared_ptr< Buffers::VolumeGridBuffer > &volume, const std::string &suggested_name)
Present a native save-file dialog filtered to volume formats and save volume to the chosen path via I...
std::shared_ptr< Buffers::VideoContainerBuffer > get_associated_buffer(const std::shared_ptr< Kakshya::VideoStreamContainer > &container)
The buffer a video or camera container was hooked to.
bool save_image(const std::shared_ptr< Buffers::TextureBuffer > &buffer, const std::string &suggested_name)
Present a native save-file dialog filtered to image formats and save buffer to the chosen path via IO...
std::shared_ptr< Nodes::Network::MeshNetwork > choose_mesh_network(IO::TextureResolver resolver)
Present a native open-file dialog filtered to 3D model formats and load the chosen file as a MeshNetw...
bool save_spatial(std::vector< IO::SpatialCaptureSource > sources, const std::string &suggested_name)
Present a native save-file dialog filtered to Alembic and write every source once via IOManager::save...
bool is_audio(const fs::path &filepath)
bool save_mesh(const std::shared_ptr< Buffers::MeshBuffer > &buffer, const std::string &suggested_name)
Present a native save-file dialog filtered to 3D model formats and save buffer to the chosen path via...
std::vector< std::shared_ptr< Buffers::MeshBuffer > > choose_mesh()
Present a native open-file dialog filtered to 3D model formats and load the chosen file via IOManager...
std::shared_ptr< Kakshya::SoundFileContainer > choose_audio()
Present a native open-file dialog filtered to audio formats and load the chosen file via IOManager::l...
std::shared_ptr< Kakshya::CompositeContainer > choose_composite()
Choose a CSV or TSV file and load it as a CompositeContainer.
std::shared_ptr< Kakshya::CameraContainer > choose_camera(bool choose_mode)
Let the user pick a camera, and optionally a capture mode, then open it via IOManager::open_camera().
std::shared_ptr< Buffers::VolumeGridBuffer > choose_volume()
Present a native open-file dialog filtered to volume formats and load the chosen file via IOManager::...
std::vector< std::shared_ptr< Buffers::SoundContainerBuffer > > get_associated_buffers(const std::shared_ptr< Kakshya::SoundFileContainer > &container)
The per-channel buffers an audio container was hooked to.
bool save_audio(const std::shared_ptr< Kakshya::SoundStreamContainer > &container, const std::string &suggested_name)
Present a native save-file dialog and write container to the chosen path via IOManager::write().
bool save_composite(const std::shared_ptr< Kakshya::CompositeContainer > &container, const std::string &suggested_name)
Choose a CSV or TSV destination and save a CompositeContainer.
Core::Engine & get_context()
Gets the default engine instance.
std::shared_ptr< IO::IOManager > get_io_manager()
Retrieves the global IOManager instance for file loading and buffer management.
std::vector< std::shared_ptr< Buffers::SoundContainerBuffer > > prepare_audio_buffers(const std::shared_ptr< Kakshya::SoundFileContainer > &container)
Constructs and initializes per-channel SoundContainerBuffers without registering them.
bool is_composite(const fs::path &filepath)
std::shared_ptr< Kakshya::DynamicSoundStream > choose_audio_bounded(uint64_t max_frames, bool truncate)
Present a native open-file dialog filtered to audio formats and load the chosen file via IOManager::l...
IO::VideoLoadResult choose_video(const IO::VideoLoadConfig &config)
Present a native open-file dialog filtered to video formats and load the chosen file via IOManager::l...
Main namespace for the Maya Flux audio engine.
std::string device_name
Platform device string.
std::string display_name
Human-readable device name for a chooser.
Configuration for opening a camera device via FFmpeg.
A requested capture mode offered by a source, for a chooser.
Configuration for image writing.
Configuration for model writing.
Configuration for volume writing.