Blender V5.0
sound_ops.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstddef>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_listbase.h"
16#include "BLI_path_utils.hh"
17#include "BLI_string.h"
18#include "BLI_utildefines.h"
19
20#include "DNA_scene_types.h"
21#include "DNA_sequence_types.h"
22#include "DNA_sound_types.h"
23#include "DNA_space_types.h"
24
25#include "BKE_context.hh"
26#include "BKE_fcurve.hh"
27#include "BKE_global.hh"
28#include "BKE_lib_id.hh"
29#include "BKE_library.hh"
30#include "BKE_main.hh"
31#include "BKE_packedFile.hh"
32#include "BKE_report.hh"
33#include "BKE_scene.hh"
34#include "BKE_sound.h"
35
36#include "RNA_access.hh"
37#include "RNA_define.hh"
38#include "RNA_enum_types.hh"
39#include "RNA_prototypes.hh"
40
41#include "SEQ_iterator.hh"
42#include "SEQ_sequencer.hh"
43
44#include "UI_interface.hh"
46
47#include "WM_api.hh"
48#include "WM_types.hh"
49
50#ifdef WITH_AUDASPACE
51# include <AUD_Special.h>
52#endif
53
55
56#include "ED_sound.hh"
57#include "ED_util.hh"
58
59/******************** open sound operator ********************/
60
61static void sound_open_cancel(bContext * /*C*/, wmOperator *op)
62{
63 MEM_delete(static_cast<PropertyPointerRNA *>(op->customdata));
64 op->customdata = nullptr;
65}
66
68{
69 PropertyPointerRNA *pprop;
70
71 op->customdata = pprop = MEM_new<PropertyPointerRNA>(__func__);
73}
74
75#ifdef WITH_AUDASPACE
77{
78 char filepath[FILE_MAX];
79 bSound *sound;
80 PropertyPointerRNA *pprop;
81 Main *bmain = CTX_data_main(C);
82
83 RNA_string_get(op->ptr, "filepath", filepath);
84 sound = BKE_sound_new_file(bmain, filepath);
85
86 if (!op->customdata) {
87 sound_open_init(C, op);
88 }
89
90 if (RNA_boolean_get(op->ptr, "mono")) {
91 sound->flags |= SOUND_FLAGS_MONO;
92 }
93
94 if (RNA_boolean_get(op->ptr, "cache")) {
95 sound->flags |= SOUND_FLAGS_CACHING;
96 }
97
98 /* hook into UI */
99 pprop = static_cast<PropertyPointerRNA *>(op->customdata);
100
101 if (pprop->prop) {
102 /* when creating new ID blocks, use is already 1, but RNA
103 * pointer use also increases user, so this compensates it */
104 id_us_min(&sound->id);
105
106 PointerRNA idptr = RNA_id_pointer_create(&sound->id);
107 RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, nullptr);
108 RNA_property_update(C, &pprop->ptr, pprop->prop);
109 }
110
112
113 MEM_delete(pprop);
114 return OPERATOR_FINISHED;
115}
116
117#else /* WITH_AUDASPACE */
118
120{
121 BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
122
123 return OPERATOR_CANCELLED;
124}
125
126#endif
127
129{
130 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
131 return sound_open_exec(C, op);
132 }
133
134 sound_open_init(C, op);
135
136 return WM_operator_filesel(C, op, event);
137}
138
140{
141 /* identifiers */
142 ot->name = "Open Sound";
143 ot->description = "Load a sound file";
144 ot->idname = "SOUND_OT_open";
145
146 /* API callbacks. */
147 ot->exec = sound_open_exec;
148 ot->invoke = sound_open_invoke;
149 ot->cancel = sound_open_cancel;
150
151 /* flags */
153
154 /* properties */
162 RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
163 RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
164}
165
167{
168 /* identifiers */
169 ot->name = "Open Sound Mono";
170 ot->description = "Load a sound file as mono";
171 ot->idname = "SOUND_OT_open_mono";
172
173 /* API callbacks. */
174 ot->exec = sound_open_exec;
175 ot->invoke = sound_open_invoke;
176 ot->cancel = sound_open_cancel;
177
178 /* flags */
180
181 /* properties */
189 RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
190 RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
191}
192
193/* ******************************************************* */
194
195static void sound_update_animation_flags(Scene *scene);
196
197static bool sound_update_animation_flags_fn(Strip *strip, void *user_data)
198{
199 const FCurve *fcu;
200 Scene *scene = (Scene *)user_data;
201 bool driven;
202
203 fcu = id_data_find_fcurve(&scene->id, strip, &RNA_Strip, "volume", 0, &driven);
204 if (fcu || driven) {
206 }
207 else {
209 }
210
211 fcu = id_data_find_fcurve(&scene->id, strip, &RNA_Strip, "pitch", 0, &driven);
212 if (fcu || driven) {
214 }
215 else {
217 }
218
219 fcu = id_data_find_fcurve(&scene->id, strip, &RNA_Strip, "pan", 0, &driven);
220 if (fcu || driven) {
222 }
223 else {
225 }
226
227 if (strip->type == STRIP_TYPE_SCENE) {
228 /* TODO(sergey): For now we do manual recursion into the scene strips,
229 * but perhaps it should be covered by recursive_apply?
230 */
232 }
233
234 return true;
235}
236
238{
239 const FCurve *fcu;
240 bool driven;
241
242 if (scene->id.tag & ID_TAG_DOIT) {
243 return;
244 }
245 scene->id.tag |= ID_TAG_DOIT;
246
247 if (scene->ed != nullptr) {
249 }
250
251 fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
252 if (fcu || driven) {
254 }
255 else {
257 }
258}
259
269
271{
272 /*
273 * This operator is needed to set a correct state of the sound animation
274 * System. Unfortunately there's no really correct place to call the exec
275 * function, that's why I made it an operator that's only visible in the
276 * search menu. Apart from that the bake animation operator calls it too.
277 */
278
279 /* identifiers */
280 ot->name = "Update Animation";
281 ot->description = "Update animation flags";
282 ot->idname = "SOUND_OT_update_animation_flags";
283
284 /* API callbacks. */
286
287 /* flags */
288 ot->flag = OPTYPE_REGISTER;
289}
290
291/* ******************************************************* */
292
294{
295 Scene *scene = CTX_data_scene(C);
296 /* NOTE: We will be forcefully evaluating dependency graph at every frame, so no need to ensure
297 * current scene state is evaluated as it will be lost anyway. */
299 int oldfra = scene->r.cfra;
300 int cfra;
301
303
304 for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
305 scene->r.cfra = cfra;
306 /* Make sure the camera is updated, since it will affect stereo/surround output. */
309 }
310
311 scene->r.cfra = oldfra;
313
314 return OPERATOR_FINISHED;
315}
316
318{
319 /* identifiers */
320 ot->name = "Update Animation Cache";
321 ot->description = "Update the audio animation cache";
322 ot->idname = "SOUND_OT_bake_animation";
323
324 /* API callbacks. */
326
327 /* flags */
328 ot->flag = OPTYPE_REGISTER;
329}
330
331/******************** mixdown operator ********************/
332
334{
335#ifdef WITH_AUDASPACE
336 char filepath[FILE_MAX];
339 Main *bmain = CTX_data_main(C);
340 int split;
341
342 int bitrate, accuracy;
343 AUD_DeviceSpecs specs;
344 AUD_Container container;
345 AUD_Codec codec;
346 int result;
347 char error_message[1024] = {'\0'};
348
350
351 RNA_string_get(op->ptr, "filepath", filepath);
352 bitrate = RNA_int_get(op->ptr, "bitrate") * 1000;
353 accuracy = RNA_int_get(op->ptr, "accuracy");
354 specs.format = AUD_SampleFormat(RNA_enum_get(op->ptr, "format"));
355 container = AUD_Container(RNA_enum_get(op->ptr, "container"));
356 codec = AUD_Codec(RNA_enum_get(op->ptr, "codec"));
357 split = RNA_boolean_get(op->ptr, "split_channels");
358 specs.channels = AUD_Channels(RNA_enum_get(op->ptr, "channels"));
359 specs.rate = RNA_int_get(op->ptr, "mixrate");
360
361 BLI_path_abs(filepath, BKE_main_blendfile_path(bmain));
362
363 const double fps = double(scene_eval->r.frs_sec) / double(scene_eval->r.frs_sec_base);
364 const int start_frame = scene_eval->r.sfra;
365 const int end_frame = scene_eval->r.efra;
366
367 if (split) {
368 result = AUD_mixdown_per_channel(scene_eval->sound_scene,
369 start_frame * specs.rate / fps,
370 (end_frame - start_frame + 1) * specs.rate / fps,
371 accuracy,
372 filepath,
373 specs,
374 container,
375 codec,
376 bitrate,
377 AUD_RESAMPLE_QUALITY_MEDIUM,
378 nullptr,
379 nullptr,
380 error_message,
381 sizeof(error_message));
382 }
383 else {
384 result = AUD_mixdown(scene_eval->sound_scene,
385 start_frame * specs.rate / fps,
386 (end_frame - start_frame + 1) * specs.rate / fps,
387 accuracy,
388 filepath,
389 specs,
390 container,
391 codec,
392 bitrate,
393 AUD_RESAMPLE_QUALITY_MEDIUM,
394 nullptr,
395 nullptr,
396 error_message,
397 sizeof(error_message));
398 }
399
400 BKE_sound_reset_scene_specs(scene_eval);
401
402 if (!result) {
403 BKE_report(op->reports, RPT_ERROR, error_message);
404 return OPERATOR_CANCELLED;
405 }
406#else /* WITH_AUDASPACE */
407 (void)C;
408 (void)op;
409#endif /* WITH_AUDASPACE */
410 return OPERATOR_FINISHED;
411}
412
413#ifdef WITH_AUDASPACE
414static const EnumPropertyItem container_items[] = {
415# ifdef WITH_FFMPEG
416 {AUD_CONTAINER_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
417 {AUD_CONTAINER_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
418# endif
419 {AUD_CONTAINER_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
420# ifdef WITH_FFMPEG
421 {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "MKV", "Matroska"},
422 {AUD_CONTAINER_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
423 {AUD_CONTAINER_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
424# endif
425 {AUD_CONTAINER_OGG, "OGG", 0, "OGG", "Xiph.Org Ogg Container"},
426 {AUD_CONTAINER_WAV, "WAV", 0, "WAV", "Waveform Audio File Format"},
427 {0, nullptr, 0, nullptr, nullptr},
428};
429
430static const char *snd_ext_sound[] = {
431 ".ac3",
432 ".flac",
433 ".mkv",
434 ".mp2",
435 ".mp3",
436 ".ogg",
437 ".wav",
438 ".aac",
439 nullptr,
440};
441
442static bool sound_mixdown_check(bContext * /*C*/, wmOperator *op)
443{
444 AUD_Container container = AUD_Container(RNA_enum_get(op->ptr, "container"));
445
446 const char *extension = nullptr;
447
448 const EnumPropertyItem *item = container_items;
449 while (item->identifier != nullptr) {
450 if (item->value == container) {
451 const char **ext = snd_ext_sound;
452 while (*ext != nullptr) {
453 if (STRCASEEQ(*ext + 1, item->name)) {
454 extension = *ext;
455 break;
456 }
457
458 ext++;
459 }
460 }
461 item++;
462 }
463
464 if (extension) {
465 PropertyRNA *prop;
466 char filepath[FILE_MAX];
467
468 int check;
469
470 prop = RNA_struct_find_property(op->ptr, "filepath");
471 RNA_property_string_get(op->ptr, prop, filepath);
472
473 if (BLI_path_extension_check_array(filepath, snd_ext_sound)) {
474 check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
475 }
476 else {
477 check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
478 }
479
480 if (!check) {
481 return check;
482 }
483
484 RNA_property_string_set(op->ptr, prop, filepath);
485 return true;
486 }
487
488 return false;
489}
490
491#endif /* WITH_AUDASPACE */
492
494{
495 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
496 return sound_mixdown_exec(C, op);
497 }
498
499 return WM_operator_filesel(C, op, event);
500}
501
502#ifdef WITH_AUDASPACE
503
504static bool sound_mixdown_draw_check_prop(PointerRNA * /*ptr*/,
505 PropertyRNA *prop,
506 void * /*user_data*/)
507{
508 const char *prop_id = RNA_property_identifier(prop);
509 return !STR_ELEM(prop_id, "filepath", "directory", "filename");
510}
511
512static void sound_mixdown_draw(bContext *C, wmOperator *op)
513{
514 static const EnumPropertyItem pcm_format_items[] = {
515 {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"},
516 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
517# ifdef WITH_SNDFILE
518 {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
519# endif
520 {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
521 {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"},
522 {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"},
523 {0, nullptr, 0, nullptr, nullptr},
524 };
525
526 static const EnumPropertyItem mp3_format_items[] = {
527 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
528 {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
529 {0, nullptr, 0, nullptr, nullptr},
530 };
531
532# ifdef WITH_SNDFILE
533 static const EnumPropertyItem flac_format_items[] = {
534 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
535 {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
536 {0, nullptr, 0, nullptr, nullptr},
537 };
538# endif
539
540 static const EnumPropertyItem all_codec_items[] = {
541 {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
542 {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
543 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
544 {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
545 {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
546 {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
547 {AUD_CODEC_OPUS, "OPUS", 0, "Opus", "Opus Interactive Audio Codec"},
548 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
549 {0, nullptr, 0, nullptr, nullptr},
550 };
551
552 static const EnumPropertyItem ogg_codec_items[] = {
553 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
554 {AUD_CODEC_OPUS, "OPUS", 0, "Opus", "Opus Interactive Audio Codec"},
555 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
556 {0, nullptr, 0, nullptr, nullptr},
557 };
558
559 uiLayout *layout = op->layout;
561 PropertyRNA *prop_format;
562 PropertyRNA *prop_codec;
563 PropertyRNA *prop_bitrate;
564
565 layout->use_property_split_set(true);
566 layout->use_property_decorate_set(false);
567
568 AUD_Container container = AUD_Container(RNA_enum_get(op->ptr, "container"));
569 AUD_Codec codec = AUD_Codec(RNA_enum_get(op->ptr, "codec"));
570
571 prop_format = RNA_struct_find_property(op->ptr, "format");
572 prop_codec = RNA_struct_find_property(op->ptr, "codec");
573 prop_bitrate = RNA_struct_find_property(op->ptr, "bitrate");
574
578
579 switch (container) {
580 case AUD_CONTAINER_AAC:
581 RNA_def_property_enum_items(prop_codec, all_codec_items);
582 RNA_enum_set(op->ptr, "codec", AUD_CODEC_AAC);
583 RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
584 break;
585 case AUD_CONTAINER_AC3:
586 RNA_def_property_enum_items(prop_codec, all_codec_items);
587 RNA_enum_set(op->ptr, "codec", AUD_CODEC_AC3);
588 RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
589 break;
590 case AUD_CONTAINER_FLAC:
591 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
592 RNA_def_property_enum_items(prop_codec, all_codec_items);
593 RNA_enum_set(op->ptr, "codec", AUD_CODEC_FLAC);
594# ifdef WITH_SNDFILE
596 RNA_def_property_enum_items(prop_format, flac_format_items);
597# else
598 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
599# endif
600 break;
601 case AUD_CONTAINER_MATROSKA:
603 RNA_def_property_enum_items(prop_codec, all_codec_items);
604
605 switch (codec) {
606 case AUD_CODEC_AAC:
607 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
608 break;
609 case AUD_CODEC_AC3:
610 RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
611 break;
612 case AUD_CODEC_FLAC:
613 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
614 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
615 break;
616 case AUD_CODEC_MP2:
617 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
618 break;
619 case AUD_CODEC_MP3:
620 RNA_def_property_enum_items(prop_format, mp3_format_items);
622 break;
623 case AUD_CODEC_PCM:
624 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
625 RNA_def_property_enum_items(prop_format, pcm_format_items);
627 break;
628 case AUD_CODEC_VORBIS:
629 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
630 break;
631 default:
632 break;
633 }
634
635 break;
636 case AUD_CONTAINER_MP2:
637 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
638 RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP2);
639 RNA_def_property_enum_items(prop_codec, all_codec_items);
640 break;
641 case AUD_CONTAINER_MP3:
643 RNA_def_property_enum_items(prop_format, mp3_format_items);
644 RNA_def_property_enum_items(prop_codec, all_codec_items);
645 RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP3);
646 break;
647 case AUD_CONTAINER_OGG:
649 RNA_def_property_enum_items(prop_codec, ogg_codec_items);
650 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
651 break;
652 case AUD_CONTAINER_WAV:
653 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
655 RNA_def_property_enum_items(prop_format, pcm_format_items);
656 RNA_def_property_enum_items(prop_codec, all_codec_items);
657 RNA_enum_set(op->ptr, "codec", AUD_CODEC_PCM);
658 break;
659 default:
660 break;
661 }
662
664
665 /* main draw call */
666 uiDefAutoButsRNA(layout,
667 &ptr,
668 sound_mixdown_draw_check_prop,
669 nullptr,
670 nullptr,
672 false);
673}
674#endif /* WITH_AUDASPACE */
675
677{
678#ifdef WITH_AUDASPACE
679 static const EnumPropertyItem format_items[] = {
680 {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"},
681 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
682 {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
683 {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
684 {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"},
685 {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"},
686 {0, nullptr, 0, nullptr, nullptr},
687 };
688
689 static const EnumPropertyItem codec_items[] = {
690# ifdef WITH_FFMPEG
691 {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
692 {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
693# endif
694 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
695# ifdef WITH_FFMPEG
696 {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
697 {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
698# endif
699 {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
700 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
701 {0, nullptr, 0, nullptr, nullptr},
702 };
703
704 static const EnumPropertyItem channel_items[] = {
705 {AUD_CHANNELS_MONO, "MONO", 0, "Mono", "Single audio channel"},
706 {AUD_CHANNELS_STEREO, "STEREO", 0, "Stereo", "Stereo audio channels"},
707 {AUD_CHANNELS_STEREO_LFE, "STEREO_LFE", 0, "Stereo LFE", "Stereo with LFE channel"},
708 {AUD_CHANNELS_SURROUND4, "SURROUND4", 0, "4 Channels", "4 channel surround sound"},
709 {AUD_CHANNELS_SURROUND5, "SURROUND5", 0, "5 Channels", "5 channel surround sound"},
710 {AUD_CHANNELS_SURROUND51, "SURROUND51", 0, "5.1 Surround", "5.1 surround sound"},
711 {AUD_CHANNELS_SURROUND61, "SURROUND61", 0, "6.1 Surround", "6.1 surround sound"},
712 {AUD_CHANNELS_SURROUND71, "SURROUND71", 0, "7.1 Surround", "7.1 surround sound"},
713 {0, nullptr, 0, nullptr, nullptr}};
714
715#endif /* WITH_AUDASPACE */
716
717 /* identifiers */
718 ot->name = "Mixdown";
719 ot->description = "Mix the scene's audio to a sound file";
720 ot->idname = "SOUND_OT_mixdown";
721
722 /* API callbacks. */
723 ot->exec = sound_mixdown_exec;
724 ot->invoke = sound_mixdown_invoke;
725
726#ifdef WITH_AUDASPACE
727 ot->check = sound_mixdown_check;
728 ot->ui = sound_mixdown_draw;
729#endif
730 /* flags */
731 ot->flag = OPTYPE_REGISTER;
732
733 /* properties */
737 FILE_SAVE,
741#ifdef WITH_AUDASPACE
743 ot->srna,
744 "accuracy",
745 1024,
746 1,
747 16777216,
748 "Accuracy",
749 "Sample accuracy, important for animation data (the lower the value, the more accurate)",
750 1,
751 16777216);
753 ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
754 RNA_def_enum(ot->srna, "codec", codec_items, AUD_CODEC_FLAC, "Codec", "Audio Codec");
756 ot->srna, "channels", channel_items, AUD_CHANNELS_STEREO, "Channels", "Audio channel count");
757 RNA_def_enum(ot->srna, "format", format_items, AUD_FORMAT_S16, "Format", "Sample format");
758 RNA_def_int(ot->srna,
759 "mixrate",
760 48000,
761 8000,
762 192000,
763 "Sample Rate",
764 "Sample rate in samples/s",
765 8000,
766 192000);
767 RNA_def_int(ot->srna, "bitrate", 192, 32, 512, "Bitrate", "Bitrate in kbit/s", 32, 512);
768 RNA_def_boolean(ot->srna,
769 "split_channels",
770 false,
771 "Split channels",
772 "Each channel will be rendered into a mono file");
773#endif /* WITH_AUDASPACE */
774}
775
776/* ******************************************************* */
777
778static bool sound_poll(bContext *C)
779{
781
782 if (!ed || !ed->act_strip || ed->act_strip->type != STRIP_TYPE_SOUND_RAM) {
783 return false;
784 }
785
786 return true;
787}
788/********************* pack operator *********************/
789
791{
792 Main *bmain = CTX_data_main(C);
794 bSound *sound;
795
796 if (!ed || !ed->act_strip || ed->act_strip->type != STRIP_TYPE_SOUND_RAM) {
797 return OPERATOR_CANCELLED;
798 }
799
800 sound = ed->act_strip->sound;
801
802 if (!sound || sound->packedfile) {
803 return OPERATOR_CANCELLED;
804 }
805
807 op->reports, sound->filepath, ID_BLEND_PATH(bmain, &sound->id));
808
809 DEG_id_tag_update_ex(bmain, &sound->id, ID_RECALC_AUDIO);
810
811 return OPERATOR_FINISHED;
812}
813
815{
816 /* identifiers */
817 ot->name = "Pack Sound";
818 ot->description = "Pack the sound into the current blend file";
819 ot->idname = "SOUND_OT_pack";
820
821 /* API callbacks. */
822 ot->exec = sound_pack_exec;
823 ot->poll = sound_poll;
824
825 /* flags */
827}
828
829/********************* unpack operator *********************/
830
832{
833 Main *bmain = CTX_data_main(C);
834 int method = RNA_enum_get(op->ptr, "method");
835 bSound *sound = nullptr;
836
837 /* find the supplied image by name */
838 if (RNA_struct_property_is_set(op->ptr, "id")) {
839 char sndname[MAX_ID_NAME - 2];
840 RNA_string_get(op->ptr, "id", sndname);
841 sound = static_cast<bSound *>(BLI_findstring(&bmain->sounds, sndname, offsetof(ID, name) + 2));
842 }
843
844 if (!sound || !sound->packedfile) {
845 return OPERATOR_CANCELLED;
846 }
847
848 if (!ID_IS_EDITABLE(&sound->id)) {
849 BKE_report(op->reports, RPT_ERROR, "Sound is not editable");
850 return OPERATOR_CANCELLED;
851 }
852
853 if (G.fileflags & G_FILE_AUTOPACK) {
856 "AutoPack is enabled, so image will be packed again on file save");
857 }
858
859 BKE_packedfile_unpack_sound(bmain, op->reports, sound, ePF_FileStatus(method));
860
861 return OPERATOR_FINISHED;
862}
863
865{
867 bSound *sound;
868
869 if (RNA_struct_property_is_set(op->ptr, "id")) {
870 return sound_unpack_exec(C, op);
871 }
872
873 if (!ed || !ed->act_strip || ed->act_strip->type != STRIP_TYPE_SOUND_RAM) {
874 return OPERATOR_CANCELLED;
875 }
876
877 sound = ed->act_strip->sound;
878
879 if (!sound || !sound->packedfile) {
880 return OPERATOR_CANCELLED;
881 }
882
883 if (!ID_IS_EDITABLE(&sound->id)) {
884 BKE_report(op->reports, RPT_ERROR, "Sound is not editable");
885 return OPERATOR_CANCELLED;
886 }
887
888 if (G.fileflags & G_FILE_AUTOPACK) {
891 "AutoPack is enabled, so image will be packed again on file save");
892 }
893
895 C, "SOUND_OT_unpack", sound->id.name + 2, sound->filepath, "sounds", sound->packedfile);
896
897 return OPERATOR_FINISHED;
898}
899
901{
902 /* identifiers */
903 ot->name = "Unpack Sound";
904 ot->description = "Unpack the sound to the samples filename";
905 ot->idname = "SOUND_OT_unpack";
906
907 /* API callbacks. */
908 ot->exec = sound_unpack_exec;
909 ot->invoke = sound_unpack_invoke;
910 ot->poll = sound_poll;
911
912 /* flags */
914
915 /* properties */
917 ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
918 /* XXX: weak!, will fail with library, name collisions */
920 ot->srna, "id", nullptr, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack");
921}
922
923/* ******************************************************* */
924
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
Scene * CTX_data_sequencer_scene(const bContext *C)
FCurve * id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, bool *r_driven)
@ G_FILE_AUTOPACK
void BKE_main_id_tag_idcode(Main *mainvar, short type, int tag, bool value)
Definition lib_id.cc:1217
void id_us_min(ID *id)
Definition lib_id.cc:366
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
int BKE_packedfile_unpack_sound(Main *bmain, ReportList *reports, bSound *sound, enum ePF_FileStatus how)
PackedFile * BKE_packedfile_new(ReportList *reports, const char *filepath_rel, const char *basepath)
ePF_FileStatus
@ PF_USE_LOCAL
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2265
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2700
struct bSound * BKE_sound_new_file(struct Main *bmain, const char *filepath)
void BKE_sound_reset_scene_specs(struct Scene *scene)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool BLI_path_extension_check_array(const char *path, const char **ext_array) ATTR_NONNULL(1
#define FILE_MAX
bool BLI_path_extension_replace(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
#define STR_ELEM(...)
Definition BLI_string.h:661
#define STRCASEEQ(a, b)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ ID_RECALC_AUDIO
Definition DNA_ID.h:1132
@ ID_RECALC_SEQUENCER_STRIPS
Definition DNA_ID.h:1122
#define MAX_ID_NAME
Definition DNA_ID.h:373
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:685
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
@ ID_SCE
@ AUDIO_VOLUME_ANIMATED
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_SOUND_RAM
@ SEQ_AUDIO_PITCH_ANIMATED
@ SEQ_AUDIO_VOLUME_ANIMATED
@ SEQ_AUDIO_PAN_ANIMATED
@ SOUND_FLAGS_MONO
@ SOUND_FLAGS_CACHING
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_TYPE_MOVIE
@ FILE_TYPE_SOUND
@ FILE_TYPE_FOLDER
@ FILE_DEFAULTDISPLAY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void unpack_menu(bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, PackedFile *pf)
Definition ed_util.cc:368
static void split(const char *text, const char *seps, char ***str, int *count)
Read Guarded memory(de)allocation.
@ PROP_HIDDEN
Definition RNA_types.hh:338
#define C
Definition RandGen.cpp:29
@ UI_BUT_LABEL_ALIGN_NONE
eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr, bool(*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data, PropertyRNA *prop_activate_init, eButLabelAlign label_align, bool compact)
void UI_context_active_but_prop_get_templateID(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop)
@ WM_FILESEL_RELPATH
Definition WM_api.hh:1121
@ WM_FILESEL_SHOW_PROPS
Definition WM_api.hh:1127
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1124
@ FILE_OPENFILE
Definition WM_api.hh:1133
@ FILE_SAVE
Definition WM_api.hh:1134
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
BPy_StructRNA * depsgraph
#define offsetof(t, d)
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
#define G(x, y, z)
void foreach_strip(ListBase *seqbase, ForEachFunc callback, void *user_data)
Definition iterator.cc:59
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:286
const char * name
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
int RNA_int_get(PointerRNA *ptr, const char *name)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
std::string RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
void RNA_def_property_clear_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_unpack_method_items[]
static void SOUND_OT_pack(wmOperatorType *ot)
Definition sound_ops.cc:814
static wmOperatorStatus sound_pack_exec(bContext *C, wmOperator *op)
Definition sound_ops.cc:790
static void SOUND_OT_open(wmOperatorType *ot)
Definition sound_ops.cc:139
static void SOUND_OT_open_mono(wmOperatorType *ot)
Definition sound_ops.cc:166
static void sound_open_cancel(bContext *, wmOperator *op)
Definition sound_ops.cc:61
static wmOperatorStatus sound_update_animation_flags_exec(bContext *C, wmOperator *)
Definition sound_ops.cc:260
static wmOperatorStatus sound_mixdown_exec(bContext *C, wmOperator *op)
Definition sound_ops.cc:333
void ED_operatortypes_sound()
Definition sound_ops.cc:925
static bool sound_poll(bContext *C)
Definition sound_ops.cc:778
static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
Definition sound_ops.cc:270
static wmOperatorStatus sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition sound_ops.cc:864
static wmOperatorStatus sound_unpack_exec(bContext *C, wmOperator *op)
Definition sound_ops.cc:831
static wmOperatorStatus sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition sound_ops.cc:493
static void SOUND_OT_bake_animation(wmOperatorType *ot)
Definition sound_ops.cc:317
static bool sound_update_animation_flags_fn(Strip *strip, void *user_data)
Definition sound_ops.cc:197
static void sound_update_animation_flags(Scene *scene)
Definition sound_ops.cc:237
static void SOUND_OT_mixdown(wmOperatorType *ot)
Definition sound_ops.cc:676
static void SOUND_OT_unpack(wmOperatorType *ot)
Definition sound_ops.cc:900
static wmOperatorStatus sound_open_exec(bContext *, wmOperator *op)
Definition sound_ops.cc:119
static wmOperatorStatus sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition sound_ops.cc:128
static void sound_open_init(bContext *C, wmOperator *op)
Definition sound_ops.cc:67
static wmOperatorStatus sound_bake_animation_exec(bContext *C, wmOperator *)
Definition sound_ops.cc:293
ListBase seqbase
Strip * act_strip
const char * identifier
Definition RNA_types.hh:657
const char * name
Definition RNA_types.hh:661
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
char name[258]
Definition DNA_ID.h:432
ListBase sounds
Definition BKE_main.hh:297
PropertyRNA * prop
Definition RNA_types.hh:146
void * sound_scene
struct Editing * ed
struct RenderData r
struct AudioData audio
struct Scene * scene
struct bSound * sound
struct PackedFile * packedfile
char filepath[1024]
short flags
void use_property_decorate_set(bool is_sep)
void use_property_split_set(bool value)
StructRNA * srna
Definition WM_types.hh:1127
struct ReportList * reports
IDProperty * properties
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
wmOperatorStatus WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *)