MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Depot.cpp
Go to the documentation of this file.
1#include "Depot.hpp"
3
6
9
15
18
21
25
27
28namespace fs = std::filesystem;
29
30namespace MayaFlux {
31
32namespace {
33
34 bool require_portal(const char* caller)
35 {
38 "{}: Portal::System not initialized", caller);
39 return false;
40 }
41 return true;
42 }
43
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 = { "*" } }
47 };
48
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 = { "*" } }
52 };
53
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 = { "*" } }
57 };
58
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 = { "*" } }
62 };
63
64 const std::vector<Portal::System::Dialog::ChooserFilter> k_composite_filters {
65 { .name = "Composite data", .extensions = { "csv", "tsv" } },
66 { .name = "All Files", .extensions = { "*" } }
67 };
68
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 = { "*" } }
72 };
73
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 = { "*" } }
77 };
78
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 = { "*" } }
82 };
83
84 const std::vector<Portal::System::Dialog::ChooserFilter> k_volume_filters {
85 { .name = "Volume", .extensions = { "vdb" } },
86 { .name = "All Files", .extensions = { "*" } }
87 };
88
89 const std::vector<Portal::System::Dialog::ChooserFilter> k_spatial_filters {
90 { .name = "Alembic", .extensions = { "abc" } },
91 { .name = "All Files", .extensions = { "*" } }
92 };
93
94 bool check_extension(const fs::path& filepath, const Portal::System::Dialog::ChooserFilter& filter)
95 {
96 if (!fs::exists(filepath) || !fs::is_regular_file(filepath))
97 return false;
98
99 auto ext = filepath.extension().string();
100 if (ext.empty())
101 return false;
102
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 };
105
106 return std::ranges::any_of(filter.extensions,
107 [&](const std::string& e) { return e == bare; });
108 }
109
110} // namespace
111
112// ---------------------------------------------------------------------------
113
114std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> prepare_audio_buffers(
115 const std::shared_ptr<Kakshya::SoundFileContainer>& container)
116{
117 if (!container) {
119 "prepare_audio_buffers failed: null container");
120 return {};
121 }
122
123 uint32_t num_channels = container->get_num_channels();
124 std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> created_buffers;
125
126 for (uint32_t ch = 0; ch < num_channels; ++ch) {
127 auto buf = std::make_shared<Buffers::SoundContainerBuffer>(
128 ch, Config::get_buffer_size(), container, ch);
129 buf->initialize();
130 created_buffers.push_back(std::move(buf));
131 }
132
133 return created_buffers;
134}
135
136bool is_image(const fs::path& filepath)
137{
138 return check_extension(filepath, k_image_filters[0]);
139}
140
141bool is_audio(const fs::path& filepath)
142{
143 return check_extension(filepath, k_audio_open_filters[0]);
144}
145
146bool is_composite(const fs::path& filepath)
147{
148 return check_extension(filepath, k_composite_filters[0]);
149}
150
151std::shared_ptr<Buffers::VideoContainerBuffer> get_associated_buffer(
152 const std::shared_ptr<Kakshya::VideoStreamContainer>& container)
153{
154 const auto io = get_io_manager();
155 if (!io || !container) {
156 return nullptr;
157 }
158
159 if (const auto camera = std::dynamic_pointer_cast<Kakshya::CameraContainer>(container)) {
160 return io->get_camera_buffer(camera);
161 }
162
163 return io->get_video_buffer(container);
164}
165
166std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> get_associated_buffers(
167 const std::shared_ptr<Kakshya::SoundFileContainer>& container)
168{
169 const auto io = get_io_manager();
170 if (!io || !container) {
171 return {};
172 }
173
174 return io->get_audio_buffers(container);
175}
176
177std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> get_associated_buffers(
178 const std::shared_ptr<Kakshya::VideoFileContainer>& container)
179{
180 const auto io = get_io_manager();
181 if (!io || !container) {
182 return {};
183 }
184
185 const auto audio = io->get_extracted_audio(container);
186 return audio ? io->get_audio_buffers(audio) : std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> {};
187}
188
189// ---------------------------------------------------------------------------
190// Dialog-backed load
191// ---------------------------------------------------------------------------
192
193std::shared_ptr<Kakshya::SoundFileContainer> choose_audio()
194{
195 if (!require_portal("choose_audio"))
196 return nullptr;
197
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);
202}
203
204std::shared_ptr<Kakshya::DynamicSoundStream> choose_audio_bounded(uint64_t max_frames, bool truncate)
205{
206 if (!require_portal("choose_audio_bounded"))
207 return nullptr;
208
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);
212 },
214 k_audio_open_filters);
215}
216
218{
219 if (!require_portal("choose_video"))
220 return {};
221
222 return Portal::System::Dialog::open_file<IO::VideoLoadResult>(
223 [config](const fs::path& p) { return get_io_manager()->load_video(p.string(), config); },
225 k_video_filters);
226}
227
228std::shared_ptr<Buffers::TextureBuffer> choose_image(
229 int desired_channels, std::optional<Kakshya::Region> region)
230{
231 if (!require_portal("choose_image"))
232 return nullptr;
233
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);
237 },
239 k_image_filters);
240}
241
242std::shared_ptr<Kakshya::CompositeContainer> choose_composite()
243{
244 if (!require_portal("choose_composite"))
245 return nullptr;
246
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);
251}
252
253std::shared_ptr<Kakshya::CompositeContainer> choose_composite(
254 const Kakshya::CompositeLayout& layout, size_t batch_size)
255{
256 if (!require_portal("choose_composite"))
257 return nullptr;
258
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);
262 },
264 k_composite_filters);
265}
266
267std::vector<std::shared_ptr<Buffers::MeshBuffer>> choose_mesh()
268{
269 if (!require_portal("choose_mesh"))
270 return {};
271
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()); },
275 k_mesh_filters);
276}
277
278std::shared_ptr<Nodes::Network::MeshNetwork> choose_mesh_network(IO::TextureResolver resolver)
279{
280 if (!require_portal("choose_mesh_network"))
281 return nullptr;
282
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));
286 },
288 k_mesh_filters);
289}
290
291std::shared_ptr<Buffers::VolumeGridBuffer> choose_volume()
292{
293 if (!require_portal("choose_volume"))
294 return nullptr;
295
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()); },
299 k_volume_filters);
300}
301
302std::shared_ptr<Kakshya::CameraContainer> choose_camera(bool choose_mode)
303{
304 auto promise = std::make_shared<std::promise<std::shared_ptr<Kakshya::CameraContainer>>>();
305 auto future = promise->get_future();
306
307 const IO::FFmpegCameraReader reader;
308 auto configs = reader.enumerate_configs();
309 if (configs.empty()) {
311 "choose_camera: no cameras found");
312 return nullptr;
313 }
314
315 Portal::Forma::pick("Choose a camera", std::move(configs),
316 [](const IO::CameraConfig& config) {
317 return config.display_name.empty() ? config.device_name : config.display_name;
318 },
319 [promise, choose_mode, modes = reader.preset_modes()](std::optional<IO::CameraConfig> camera) {
320 if (!camera) {
321 promise->set_value(nullptr);
322 return;
323 }
324 if (!choose_mode) {
325 promise->set_value(get_io_manager()->open_camera(*camera));
326 return;
327 }
328 Portal::Forma::pick("Choose a mode", modes,
329 [](const IO::CameraMode& mode) { return mode.label; },
330 [promise, config = *camera](std::optional<IO::CameraMode> mode) mutable {
331 if (!mode) {
332 promise->set_value(nullptr);
333 return;
334 }
335 mode->apply(config);
336 promise->set_value(get_io_manager()->open_camera(config));
337 });
338 });
339
340 return Parallel::await_future(std::move(future));
341}
342
343// ---------------------------------------------------------------------------
344// Dialog-backed save
345// ---------------------------------------------------------------------------
346
348 const std::shared_ptr<Kakshya::SoundStreamContainer>& container,
349 const std::string& suggested_name)
350{
351 if (!require_portal("save_audio"))
352 return false;
353
354 auto iom = get_io_manager();
355 if (!iom) {
357 "save_audio: IOManager unavailable");
358 return false;
359 }
360
361 return Portal::System::Dialog::save_file<bool>(
362 [&iom, &container](const fs::path& p) {
363 iom->write(container, p.string());
364 return true;
365 },
367 suggested_name,
368 k_audio_save_filters);
369}
370
372 const std::shared_ptr<Buffers::TextureBuffer>& buffer,
373 const std::string& suggested_name)
374{
375 if (!require_portal("save_image"))
376 return false;
377
378 auto iom = get_io_manager();
379 if (!iom) {
381 "save_image: IOManager unavailable");
382 return false;
383 }
384
385 return Portal::System::Dialog::save_file<bool>(
386 [&iom, &buffer](const fs::path& p) {
387 return iom->save_image(buffer, p.string(), IO::ImageWriteOptions {});
388 },
390 suggested_name,
391 k_image_save_filters);
392}
393
395 const std::shared_ptr<Buffers::TextureBuffer>& buffer,
396 const std::string& suggested_name,
397 const IO::ImageWriteOptions& options)
398{
399 if (!require_portal("save_image"))
400 return false;
401
402 auto iom = get_io_manager();
403 if (!iom) {
405 "save_image: IOManager unavailable");
406 return false;
407 }
408
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);
412 },
414 suggested_name,
415 k_image_save_filters);
416}
417
419 const std::shared_ptr<Kakshya::CompositeContainer>& container,
420 const std::string& suggested_name)
421{
422 if (!require_portal("save_composite"))
423 return false;
424
425 auto iom = get_io_manager();
426 if (!iom) {
428 "save_composite: IOManager unavailable");
429 return false;
430 }
431
432 return Portal::System::Dialog::save_file<bool>(
433 [&iom, &container](const fs::path& p) {
434 return iom->save_composite(container, p.string());
435 },
437 suggested_name,
438 k_composite_filters);
439}
440
442 const std::shared_ptr<Buffers::MeshBuffer>& buffer,
443 const std::string& suggested_name)
444{
445 return save_mesh(buffer, suggested_name, IO::ModelWriteOptions {});
446}
447
449 const std::shared_ptr<Buffers::MeshBuffer>& buffer,
450 const std::string& suggested_name,
451 const IO::ModelWriteOptions& options)
452{
453 if (!require_portal("save_mesh"))
454 return false;
455
456 auto iom = get_io_manager();
457 if (!iom) {
459 "save_mesh: IOManager unavailable");
460 return false;
461 }
462
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);
466 },
468 suggested_name,
469 k_mesh_save_filters);
470}
471
473 const std::shared_ptr<Nodes::Network::MeshNetwork>& network,
474 const std::string& suggested_name)
475{
476 return save_mesh(network, suggested_name, IO::ModelWriteOptions {});
477}
478
480 const std::shared_ptr<Nodes::Network::MeshNetwork>& network,
481 const std::string& suggested_name,
482 const IO::ModelWriteOptions& options)
483{
484 if (!require_portal("save_mesh"))
485 return false;
486
487 auto iom = get_io_manager();
488 if (!iom) {
490 "save_mesh: IOManager unavailable");
491 return false;
492 }
493
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);
497 },
499 suggested_name,
500 k_mesh_save_filters);
501}
502
504 const std::shared_ptr<Buffers::VolumeGridBuffer>& volume,
505 const std::string& suggested_name)
506{
507 if (!require_portal("save_volume"))
508 return false;
509
510 auto iom = get_io_manager();
511 if (!iom) {
513 "save_volume: IOManager unavailable");
514 return false;
515 }
516
517 return Portal::System::Dialog::save_file<bool>(
518 [&iom, &volume](const fs::path& p) {
519 return iom->save_volume(volume, p.string(), IO::VolumeWriteOptions {});
520 },
522 suggested_name,
523 k_volume_filters);
524}
525
527 const std::shared_ptr<Buffers::VolumeGridBuffer>& volume,
528 const std::string& suggested_name,
529 const IO::VolumeWriteOptions& options)
530{
531 if (!require_portal("save_volume"))
532 return false;
533
534 auto iom = get_io_manager();
535 if (!iom) {
537 "save_volume: IOManager unavailable");
538 return false;
539 }
540
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);
544 },
546 suggested_name,
547 k_volume_filters);
548}
549
551 std::vector<IO::SpatialCaptureSource> sources,
552 const std::string& suggested_name)
553{
554 if (!require_portal("save_spatial"))
555 return false;
556
557 auto iom = get_io_manager();
558 if (!iom) {
560 "save_spatial: IOManager unavailable");
561 return false;
562 }
563
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());
567 },
569 suggested_name,
570 k_spatial_filters);
571}
572
573// ---------------------------------------------------------------------------
574
575std::shared_ptr<IO::IOManager> get_io_manager()
576{
578 return get_context().get_io_manager();
579
581 "Attempted to access IOManager before engine initialization");
582 return nullptr;
583}
584
585} // namespace MayaFlux
#define MF_ERROR(comp, ctx,...)
Core::GlobalNetworkConfig network
Definition Config.cpp:43
Core engine lifecycle and configuration API.
Dialog-backed loading and file-type helpers.
std::shared_ptr< NetworkGeometryBuffer > buffer
uint32_t mode
std::shared_ptr< IO::IOManager > get_io_manager()
Gets the IO manager.
Definition Engine.hpp:322
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.
Definition Composite.hpp:52
uint32_t get_buffer_size()
Gets the buffer size from the default engine.
Definition Config.cpp:120
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.
Definition IOManager.hpp:90
std::function< std::shared_ptr< Core::VKImage >(const std::string &)> TextureResolver
Callable that maps a raw material texture path to a GPU image.
Definition Depot.hpp:31
@ Runtime
General runtime operations (default fallback)
@ API
MayaFlux/API Wrapper and convenience functions.
T await_future(std::future< T > future)
Definition Dispatch.hpp:154
void pick(std::string title, std::vector< std::string > labels, PickCallback callback)
Open a window of clickable rows, one per label, and report the choice.
Definition Picker.cpp:46
Core::SystemFileFilter ChooserFilter
A named group of accepted file extensions.
Definition Chooser.hpp:27
bool is_initialized()
Return true if Portal::System has been initialized.
Definition System.cpp:85
bool is_engine_configured()
Checks if the default engine has currently accepted all configurations and initialized all managers.
Definition Config.cpp:58
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...
Definition Depot.cpp:228
bool is_image(const fs::path &filepath)
Definition Depot.cpp:136
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...
Definition Depot.cpp:503
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.
Definition Depot.cpp:151
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...
Definition Depot.cpp:371
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...
Definition Depot.cpp:278
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...
Definition Depot.cpp:550
bool is_audio(const fs::path &filepath)
Definition Depot.cpp:141
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...
Definition Depot.cpp:441
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...
Definition Depot.cpp:267
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...
Definition Depot.cpp:193
std::shared_ptr< Kakshya::CompositeContainer > choose_composite()
Choose a CSV or TSV file and load it as a CompositeContainer.
Definition Depot.cpp:242
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().
Definition Depot.cpp:302
std::shared_ptr< Buffers::VolumeGridBuffer > choose_volume()
Present a native open-file dialog filtered to volume formats and load the chosen file via IOManager::...
Definition Depot.cpp:291
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.
Definition Depot.cpp:166
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().
Definition Depot.cpp:347
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.
Definition Depot.cpp:418
Core::Engine & get_context()
Gets the default engine instance.
Definition Core.cpp:101
std::shared_ptr< IO::IOManager > get_io_manager()
Retrieves the global IOManager instance for file loading and buffer management.
Definition Depot.cpp:575
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.
Definition Depot.cpp:114
bool is_composite(const fs::path &filepath)
Definition Depot.cpp:146
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...
Definition Depot.cpp:204
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...
Definition Depot.cpp:217
Main namespace for the Maya Flux audio engine.
Definition Runtime.cpp:12
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.