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