Blender V4.3
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
9#include <cstddef>
10#include <cstdio>
11#include <cstdlib>
12#include <cstring>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_blenlib.h"
17#include "BLI_utildefines.h"
18
19#include "DNA_scene_types.h"
20#include "DNA_sequence_types.h"
21#include "DNA_sound_types.h"
22#include "DNA_space_types.h"
23#include "DNA_userdef_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_main.hh"
30#include "BKE_packedFile.hh"
31#include "BKE_report.hh"
32#include "BKE_scene.hh"
33#include "BKE_sound.h"
34
35#include "RNA_access.hh"
36#include "RNA_define.hh"
37#include "RNA_enum_types.hh"
38#include "RNA_prototypes.hh"
39
40#include "SEQ_iterator.hh"
41
42#include "UI_interface.hh"
43
44#include "WM_api.hh"
45#include "WM_types.hh"
46
47#ifdef WITH_AUDASPACE
48# include <AUD_Special.h>
49#endif
50
52
53#include "ED_sound.hh"
54#include "ED_util.hh"
55
56/******************** open sound operator ********************/
57
58static void sound_open_cancel(bContext * /*C*/, wmOperator *op)
59{
61 op->customdata = nullptr;
62}
63
65{
66 PropertyPointerRNA *pprop;
67
68 op->customdata = pprop = static_cast<PropertyPointerRNA *>(
69 MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA"));
71}
72
73#ifdef WITH_AUDASPACE
74static int sound_open_exec(bContext *C, wmOperator *op)
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
112 return OPERATOR_FINISHED;
113}
114
115#else /* WITH_AUDASPACE */
116
117static int sound_open_exec(bContext * /*C*/, wmOperator *op)
118{
119 BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
120
121 return OPERATOR_CANCELLED;
122}
123
124#endif
125
126static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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 */
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 */
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(Sequence *seq, 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, seq, &RNA_Sequence, "volume", 0, &driven);
202 if (fcu || driven) {
204 }
205 else {
206 seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED;
207 }
208
209 fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven);
210 if (fcu || driven) {
212 }
213 else {
214 seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED;
215 }
216
217 fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven);
218 if (fcu || driven) {
220 }
221 else {
222 seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED;
223 }
224
225 if (seq->type == SEQ_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) {
246 SEQ_for_each_callback(&scene->ed->seqbase, sound_update_animation_flags_fn, scene);
247 }
248
249 fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
250 if (fcu || driven) {
251 scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
252 }
253 else {
254 scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED;
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 */
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 */
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_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
415# endif
416 {AUD_CONTAINER_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
417# ifdef WITH_FFMPEG
418 {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "MKV", "Matroska"},
419 {AUD_CONTAINER_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
420 {AUD_CONTAINER_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
421# endif
422 {AUD_CONTAINER_OGG, "OGG", 0, "OGG", "Xiph.Org Ogg Container"},
423 {AUD_CONTAINER_WAV, "WAV", 0, "WAV", "Waveform Audio File Format"},
424 {0, nullptr, 0, nullptr, nullptr},
425};
426
427static const char *snd_ext_sound[] = {
428 ".ac3",
429 ".flac",
430 ".mkv",
431 ".mp2",
432 ".mp3",
433 ".ogg",
434 ".wav",
435 nullptr,
436};
437
438static bool sound_mixdown_check(bContext * /*C*/, wmOperator *op)
439{
440 AUD_Container container = AUD_Container(RNA_enum_get(op->ptr, "container"));
441
442 const char *extension = nullptr;
443
444 const EnumPropertyItem *item = container_items;
445 while (item->identifier != nullptr) {
446 if (item->value == container) {
447 const char **ext = snd_ext_sound;
448 while (*ext != nullptr) {
449 if (STREQ(*ext + 1, item->name)) {
450 extension = *ext;
451 break;
452 }
453
454 ext++;
455 }
456 }
457 item++;
458 }
459
460 if (extension) {
461 PropertyRNA *prop;
462 char filepath[FILE_MAX];
463
464 int check;
465
466 prop = RNA_struct_find_property(op->ptr, "filepath");
467 RNA_property_string_get(op->ptr, prop, filepath);
468
469 if (BLI_path_extension_check_array(filepath, snd_ext_sound)) {
470 check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
471 }
472 else {
473 check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
474 }
475
476 if (!check) {
477 return check;
478 }
479
480 RNA_property_string_set(op->ptr, prop, filepath);
481 return true;
482 }
483
484 return false;
485}
486
487#endif /* WITH_AUDASPACE */
488
489static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
490{
491 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
492 return sound_mixdown_exec(C, op);
493 }
494
495 return WM_operator_filesel(C, op, event);
496}
497
498#ifdef WITH_AUDASPACE
499
500static bool sound_mixdown_draw_check_prop(PointerRNA * /*ptr*/,
501 PropertyRNA *prop,
502 void * /*user_data*/)
503{
504 const char *prop_id = RNA_property_identifier(prop);
505 return !STR_ELEM(prop_id, "filepath", "directory", "filename");
506}
507
508static void sound_mixdown_draw(bContext *C, wmOperator *op)
509{
510 static const EnumPropertyItem pcm_format_items[] = {
511 {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"},
512 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
513# ifdef WITH_SNDFILE
514 {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
515# endif
516 {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
517 {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"},
518 {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"},
519 {0, nullptr, 0, nullptr, nullptr},
520 };
521
522 static const EnumPropertyItem mp3_format_items[] = {
523 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
524 {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
525 {0, nullptr, 0, nullptr, nullptr},
526 };
527
528# ifdef WITH_SNDFILE
529 static const EnumPropertyItem flac_format_items[] = {
530 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
531 {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
532 {0, nullptr, 0, nullptr, nullptr},
533 };
534# endif
535
536 static const EnumPropertyItem all_codec_items[] = {
537 {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
538 {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
539 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
540 {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
541 {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
542 {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
543 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
544 {0, nullptr, 0, nullptr, nullptr},
545 };
546
547 static const EnumPropertyItem ogg_codec_items[] = {
548 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
549 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
550 {0, nullptr, 0, nullptr, nullptr},
551 };
552
553 uiLayout *layout = op->layout;
555 PropertyRNA *prop_format;
556 PropertyRNA *prop_codec;
557 PropertyRNA *prop_bitrate;
558
559 uiLayoutSetPropSep(layout, true);
560 uiLayoutSetPropDecorate(layout, false);
561
562 AUD_Container container = AUD_Container(RNA_enum_get(op->ptr, "container"));
563 AUD_Codec codec = AUD_Codec(RNA_enum_get(op->ptr, "codec"));
564
565 prop_format = RNA_struct_find_property(op->ptr, "format");
566 prop_codec = RNA_struct_find_property(op->ptr, "codec");
567 prop_bitrate = RNA_struct_find_property(op->ptr, "bitrate");
568
572
573 switch (container) {
574 case AUD_CONTAINER_AC3:
575 RNA_def_property_enum_items(prop_codec, all_codec_items);
576 RNA_enum_set(op->ptr, "codec", AUD_CODEC_AC3);
577 RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
578 break;
579 case AUD_CONTAINER_FLAC:
580 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
581 RNA_def_property_enum_items(prop_codec, all_codec_items);
582 RNA_enum_set(op->ptr, "codec", AUD_CODEC_FLAC);
583# ifdef WITH_SNDFILE
585 RNA_def_property_enum_items(prop_format, flac_format_items);
586# else
587 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
588# endif
589 break;
590 case AUD_CONTAINER_MATROSKA:
592 RNA_def_property_enum_items(prop_codec, all_codec_items);
593
594 switch (codec) {
595 case AUD_CODEC_AAC:
596 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
597 break;
598 case AUD_CODEC_AC3:
599 RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
600 break;
601 case AUD_CODEC_FLAC:
602 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
603 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
604 break;
605 case AUD_CODEC_MP2:
606 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
607 break;
608 case AUD_CODEC_MP3:
609 RNA_def_property_enum_items(prop_format, mp3_format_items);
611 break;
612 case AUD_CODEC_PCM:
613 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
614 RNA_def_property_enum_items(prop_format, pcm_format_items);
616 break;
617 case AUD_CODEC_VORBIS:
618 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
619 break;
620 default:
621 break;
622 }
623
624 break;
625 case AUD_CONTAINER_MP2:
626 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
627 RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP2);
628 RNA_def_property_enum_items(prop_codec, all_codec_items);
629 break;
630 case AUD_CONTAINER_MP3:
632 RNA_def_property_enum_items(prop_format, mp3_format_items);
633 RNA_def_property_enum_items(prop_codec, all_codec_items);
634 RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP3);
635 break;
636 case AUD_CONTAINER_OGG:
638 RNA_def_property_enum_items(prop_codec, ogg_codec_items);
639 RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
640 break;
641 case AUD_CONTAINER_WAV:
642 RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
644 RNA_def_property_enum_items(prop_format, pcm_format_items);
645 RNA_def_property_enum_items(prop_codec, all_codec_items);
646 RNA_enum_set(op->ptr, "codec", AUD_CODEC_PCM);
647 break;
648 default:
649 break;
650 }
651
653
654 /* main draw call */
655 uiDefAutoButsRNA(layout,
656 &ptr,
657 sound_mixdown_draw_check_prop,
658 nullptr,
659 nullptr,
661 false);
662}
663#endif /* WITH_AUDASPACE */
664
666{
667#ifdef WITH_AUDASPACE
668 static const EnumPropertyItem format_items[] = {
669 {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"},
670 {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"},
671 {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"},
672 {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"},
673 {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"},
674 {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"},
675 {0, nullptr, 0, nullptr, nullptr},
676 };
677
678 static const EnumPropertyItem codec_items[] = {
679# ifdef WITH_FFMPEG
680 {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
681 {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
682# endif
683 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
684# ifdef WITH_FFMPEG
685 {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
686 {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
687# endif
688 {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
689 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
690 {0, nullptr, 0, nullptr, nullptr},
691 };
692
693 static const EnumPropertyItem channel_items[] = {
694 {AUD_CHANNELS_MONO, "MONO", 0, "Mono", "Single audio channel"},
695 {AUD_CHANNELS_STEREO, "STEREO", 0, "Stereo", "Stereo audio channels"},
696 {AUD_CHANNELS_STEREO_LFE, "STEREO_LFE", 0, "Stereo LFE", "Stereo with LFE channel"},
697 {AUD_CHANNELS_SURROUND4, "SURROUND4", 0, "4 Channels", "4 channel surround sound"},
698 {AUD_CHANNELS_SURROUND5, "SURROUND5", 0, "5 Channels", "5 channel surround sound"},
699 {AUD_CHANNELS_SURROUND51, "SURROUND51", 0, "5.1 Surround", "5.1 surround sound"},
700 {AUD_CHANNELS_SURROUND61, "SURROUND61", 0, "6.1 Surround", "6.1 surround sound"},
701 {AUD_CHANNELS_SURROUND71, "SURROUND71", 0, "7.1 Surround", "7.1 surround sound"},
702 {0, nullptr, 0, nullptr, nullptr}};
703
704#endif /* WITH_AUDASPACE */
705
706 /* identifiers */
707 ot->name = "Mixdown";
708 ot->description = "Mix the scene's audio to a sound file";
709 ot->idname = "SOUND_OT_mixdown";
710
711 /* api callbacks */
714
715#ifdef WITH_AUDASPACE
716 ot->check = sound_mixdown_check;
717 ot->ui = sound_mixdown_draw;
718#endif
719 /* flags */
721
722 /* properties */
726 FILE_SAVE,
730#ifdef WITH_AUDASPACE
732 ot->srna,
733 "accuracy",
734 1024,
735 1,
736 16777216,
737 "Accuracy",
738 "Sample accuracy, important for animation data (the lower the value, the more accurate)",
739 1,
740 16777216);
742 ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
743 RNA_def_enum(ot->srna, "codec", codec_items, AUD_CODEC_FLAC, "Codec", "Audio Codec");
745 ot->srna, "channels", channel_items, AUD_CHANNELS_STEREO, "Channels", "Audio channel count");
746 RNA_def_enum(ot->srna, "format", format_items, AUD_FORMAT_S16, "Format", "Sample format");
748 "mixrate",
749 48000,
750 8000,
751 192000,
752 "Samplerate",
753 "Samplerate in samples/s",
754 8000,
755 192000);
756 RNA_def_int(ot->srna, "bitrate", 192, 32, 512, "Bitrate", "Bitrate in kbit/s", 32, 512);
758 "split_channels",
759 false,
760 "Split channels",
761 "Each channel will be rendered into a mono file");
762#endif /* WITH_AUDASPACE */
763}
764
765/* ******************************************************* */
766
767static bool sound_poll(bContext *C)
768{
769 Editing *ed = CTX_data_scene(C)->ed;
770
771 if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
772 return false;
773 }
774
775 return true;
776}
777/********************* pack operator *********************/
778
780{
781 Main *bmain = CTX_data_main(C);
782 Editing *ed = CTX_data_scene(C)->ed;
783 bSound *sound;
784
785 if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
786 return OPERATOR_CANCELLED;
787 }
788
789 sound = ed->act_seq->sound;
790
791 if (!sound || sound->packedfile) {
792 return OPERATOR_CANCELLED;
793 }
794
796 op->reports, sound->filepath, ID_BLEND_PATH(bmain, &sound->id));
797
798 DEG_id_tag_update_ex(bmain, &sound->id, ID_RECALC_AUDIO);
799
800 return OPERATOR_FINISHED;
801}
802
804{
805 /* identifiers */
806 ot->name = "Pack Sound";
807 ot->description = "Pack the sound into the current blend file";
808 ot->idname = "SOUND_OT_pack";
809
810 /* api callbacks */
812 ot->poll = sound_poll;
813
814 /* flags */
816}
817
818/********************* unpack operator *********************/
819
821{
822 Main *bmain = CTX_data_main(C);
823 int method = RNA_enum_get(op->ptr, "method");
824 bSound *sound = nullptr;
825
826 /* find the supplied image by name */
827 if (RNA_struct_property_is_set(op->ptr, "id")) {
828 char sndname[MAX_ID_NAME - 2];
829 RNA_string_get(op->ptr, "id", sndname);
830 sound = static_cast<bSound *>(BLI_findstring(&bmain->sounds, sndname, offsetof(ID, name) + 2));
831 }
832
833 if (!sound || !sound->packedfile) {
834 return OPERATOR_CANCELLED;
835 }
836
837 if (!ID_IS_EDITABLE(&sound->id)) {
838 BKE_report(op->reports, RPT_ERROR, "Sound is not editable");
839 return OPERATOR_CANCELLED;
840 }
841
842 if (G.fileflags & G_FILE_AUTOPACK) {
845 "AutoPack is enabled, so image will be packed again on file save");
846 }
847
848 BKE_packedfile_unpack_sound(bmain, op->reports, sound, ePF_FileStatus(method));
849
850 return OPERATOR_FINISHED;
851}
852
853static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
854{
855 Editing *ed = CTX_data_scene(C)->ed;
856 bSound *sound;
857
858 if (RNA_struct_property_is_set(op->ptr, "id")) {
859 return sound_unpack_exec(C, op);
860 }
861
862 if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
863 return OPERATOR_CANCELLED;
864 }
865
866 sound = ed->act_seq->sound;
867
868 if (!sound || !sound->packedfile) {
869 return OPERATOR_CANCELLED;
870 }
871
872 if (!ID_IS_EDITABLE(&sound->id)) {
873 BKE_report(op->reports, RPT_ERROR, "Sound is not editable");
874 return OPERATOR_CANCELLED;
875 }
876
877 if (G.fileflags & G_FILE_AUTOPACK) {
880 "AutoPack is enabled, so image will be packed again on file save");
881 }
882
884 C, "SOUND_OT_unpack", sound->id.name + 2, sound->filepath, "sounds", sound->packedfile);
885
886 return OPERATOR_FINISHED;
887}
888
890{
891 /* identifiers */
892 ot->name = "Unpack Sound";
893 ot->description = "Unpack the sound to the samples filename";
894 ot->idname = "SOUND_OT_unpack";
895
896 /* api callbacks */
899 ot->poll = sound_poll;
900
901 /* flags */
903
904 /* properties */
906 ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
907 /* XXX: weak!, will fail with library, name collisions */
909 ot->srna, "id", nullptr, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack");
910}
911
912/* ******************************************************* */
913
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:1191
void id_us_min(ID *id)
Definition lib_id.cc:359
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
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:125
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2213
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2647
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 struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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:653
#define STREQ(a, b)
typedef double(DMatrix)[4][4]
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_tag_update_ex(Main *bmain, 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:1099
@ ID_RECALC_SEQUENCER_STRIPS
Definition DNA_ID.h:1089
#define MAX_ID_NAME
Definition DNA_ID.h:377
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:647
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
@ ID_SCE
@ AUDIO_VOLUME_ANIMATED
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_SCENE
@ 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
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:363
static void split(const char *text, const char *seps, char ***str, int *count)
Read Guarded memory(de)allocation.
@ PROP_HIDDEN
Definition RNA_types.hh:239
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
@ 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 uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
@ WM_FILESEL_RELPATH
Definition WM_api.hh:933
@ WM_FILESEL_SHOW_PROPS
Definition WM_api.hh:939
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_OPENFILE
Definition WM_api.hh:945
@ FILE_SAVE
Definition WM_api.hh:946
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
const Depsgraph * depsgraph
#define offsetof(t, d)
void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
Definition iterator.cc:43
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
#define G(x, y, z)
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(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:803
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 bool sound_update_animation_flags_fn(Sequence *seq, void *user_data)
Definition sound_ops.cc:195
static void sound_open_cancel(bContext *, wmOperator *op)
Definition sound_ops.cc:58
static int sound_pack_exec(bContext *C, wmOperator *op)
Definition sound_ops.cc:779
static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition sound_ops.cc:126
void ED_operatortypes_sound()
Definition sound_ops.cc:914
static bool sound_poll(bContext *C)
Definition sound_ops.cc:767
static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
Definition sound_ops.cc:268
static int sound_update_animation_flags_exec(bContext *C, wmOperator *)
Definition sound_ops.cc:258
static int sound_open_exec(bContext *, wmOperator *op)
Definition sound_ops.cc:117
static int sound_mixdown_exec(bContext *C, wmOperator *op)
Definition sound_ops.cc:331
static void SOUND_OT_bake_animation(wmOperatorType *ot)
Definition sound_ops.cc:315
static int sound_bake_animation_exec(bContext *C, wmOperator *)
Definition sound_ops.cc:291
static void sound_update_animation_flags(Scene *scene)
Definition sound_ops.cc:235
static void SOUND_OT_mixdown(wmOperatorType *ot)
Definition sound_ops.cc:665
static void SOUND_OT_unpack(wmOperatorType *ot)
Definition sound_ops.cc:889
static int sound_unpack_exec(bContext *C, wmOperator *op)
Definition sound_ops.cc:820
static void sound_open_init(bContext *C, wmOperator *op)
Definition sound_ops.cc:64
static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition sound_ops.cc:853
static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition sound_ops.cc:489
Sequence * act_seq
const char * identifier
Definition RNA_types.hh:506
const char * name
Definition RNA_types.hh:510
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
ListBase sounds
Definition BKE_main.hh:230
PropertyRNA * prop
Definition RNA_types.hh:49
void * sound_scene
struct Editing * ed
struct RenderData r
struct Scene * scene
struct bSound * sound
struct PackedFile * packedfile
char filepath[1024]
short flags
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
bool(* check)(bContext *C, wmOperator *op)
Definition WM_types.hh:1014
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
StructRNA * srna
Definition WM_types.hh:1080
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
IDProperty * properties
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
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 *))
int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *)