1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2007 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup edsnd
22 */
23
24 #include <stddef.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "BLI_blenlib.h"
32 #include "BLI_utildefines.h"
33
34 #include "DNA_packedFile_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_sequence_types.h"
37 #include "DNA_sound_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_userdef_types.h"
40
41 #include "BKE_context.h"
42 #include "BKE_fcurve.h"
43 #include "BKE_global.h"
44 #include "BKE_lib_id.h"
45 #include "BKE_main.h"
46 #include "BKE_packedFile.h"
47 #include "BKE_report.h"
48 #include "BKE_scene.h"
49 #include "BKE_sequencer.h"
50 #include "BKE_sound.h"
51
52 #include "RNA_access.h"
53 #include "RNA_define.h"
54 #include "RNA_enum_types.h"
55
56 #include "UI_interface.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #ifdef WITH_AUDASPACE
62 # include <AUD_Special.h>
63 #endif
64
65 #include "DEG_depsgraph_query.h"
66
67 #include "ED_sound.h"
68 #include "ED_util.h"
69
70 /******************** open sound operator ********************/
71
sound_open_cancel(bContext * UNUSED (C),wmOperator * op)72 static void sound_open_cancel(bContext *UNUSED(C), wmOperator *op)
73 {
74 MEM_freeN(op->customdata);
75 op->customdata = NULL;
76 }
77
sound_open_init(bContext * C,wmOperator * op)78 static void sound_open_init(bContext *C, wmOperator *op)
79 {
80 PropertyPointerRNA *pprop;
81
82 op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
83 UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
84 }
85
86 #ifdef WITH_AUDASPACE
sound_open_exec(bContext * C,wmOperator * op)87 static int sound_open_exec(bContext *C, wmOperator *op)
88 {
89 char path[FILE_MAX];
90 bSound *sound;
91 PropertyPointerRNA *pprop;
92 PointerRNA idptr;
93 Main *bmain = CTX_data_main(C);
94
95 RNA_string_get(op->ptr, "filepath", path);
96 sound = BKE_sound_new_file(bmain, path);
97
98 if (!op->customdata) {
99 sound_open_init(C, op);
100 }
101
102 if (RNA_boolean_get(op->ptr, "mono")) {
103 sound->flags |= SOUND_FLAGS_MONO;
104 }
105
106 if (RNA_boolean_get(op->ptr, "cache")) {
107 sound->flags |= SOUND_FLAGS_CACHING;
108 }
109
110 /* hook into UI */
111 pprop = op->customdata;
112
113 if (pprop->prop) {
114 /* when creating new ID blocks, use is already 1, but RNA
115 * pointer use also increases user, so this compensates it */
116 id_us_min(&sound->id);
117
118 RNA_id_pointer_create(&sound->id, &idptr);
119 RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
120 RNA_property_update(C, &pprop->ptr, pprop->prop);
121 }
122
123 DEG_relations_tag_update(bmain);
124
125 MEM_freeN(op->customdata);
126 return OPERATOR_FINISHED;
127 }
128
129 #else /* WITH_AUDASPACE */
130
sound_open_exec(bContext * UNUSED (C),wmOperator * op)131 static int sound_open_exec(bContext *UNUSED(C), wmOperator *op)
132 {
133 BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
134
135 return OPERATOR_CANCELLED;
136 }
137
138 #endif
139
sound_open_invoke(bContext * C,wmOperator * op,const wmEvent * event)140 static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
141 {
142 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
143 return sound_open_exec(C, op);
144 }
145
146 sound_open_init(C, op);
147
148 return WM_operator_filesel(C, op, event);
149 }
150
SOUND_OT_open(wmOperatorType * ot)151 static void SOUND_OT_open(wmOperatorType *ot)
152 {
153 /* identifiers */
154 ot->name = "Open Sound";
155 ot->description = "Load a sound file";
156 ot->idname = "SOUND_OT_open";
157
158 /* api callbacks */
159 ot->exec = sound_open_exec;
160 ot->invoke = sound_open_invoke;
161 ot->cancel = sound_open_cancel;
162
163 /* flags */
164 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
165
166 /* properties */
167 WM_operator_properties_filesel(ot,
168 FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
169 FILE_SPECIAL,
170 FILE_OPENFILE,
171 WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
172 FILE_DEFAULTDISPLAY,
173 FILE_SORT_ALPHA);
174 RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
175 RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
176 }
177
SOUND_OT_open_mono(wmOperatorType * ot)178 static void SOUND_OT_open_mono(wmOperatorType *ot)
179 {
180 /* identifiers */
181 ot->name = "Open Sound Mono";
182 ot->description = "Load a sound file as mono";
183 ot->idname = "SOUND_OT_open_mono";
184
185 /* api callbacks */
186 ot->exec = sound_open_exec;
187 ot->invoke = sound_open_invoke;
188 ot->cancel = sound_open_cancel;
189
190 /* flags */
191 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
192
193 /* properties */
194 WM_operator_properties_filesel(ot,
195 FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
196 FILE_SPECIAL,
197 FILE_OPENFILE,
198 WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
199 FILE_DEFAULTDISPLAY,
200 FILE_SORT_ALPHA);
201 RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
202 RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
203 }
204
205 /* ******************************************************* */
206
207 static void sound_update_animation_flags(Scene *scene);
208
sound_update_animation_flags_fn(Sequence * seq,void * user_data)209 static int sound_update_animation_flags_fn(Sequence *seq, void *user_data)
210 {
211 struct FCurve *fcu;
212 Scene *scene = (Scene *)user_data;
213 bool driven;
214
215 fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven);
216 if (fcu || driven) {
217 seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED;
218 }
219 else {
220 seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED;
221 }
222
223 fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven);
224 if (fcu || driven) {
225 seq->flag |= SEQ_AUDIO_PITCH_ANIMATED;
226 }
227 else {
228 seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED;
229 }
230
231 fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven);
232 if (fcu || driven) {
233 seq->flag |= SEQ_AUDIO_PAN_ANIMATED;
234 }
235 else {
236 seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED;
237 }
238
239 if (seq->type == SEQ_TYPE_SCENE) {
240 /* TODO(sergey): For now we do manual recursion into the scene strips,
241 * but perhaps it should be covered by recursive_apply?
242 */
243 sound_update_animation_flags(seq->scene);
244 }
245
246 return 0;
247 }
248
sound_update_animation_flags(Scene * scene)249 static void sound_update_animation_flags(Scene *scene)
250 {
251 struct FCurve *fcu;
252 bool driven;
253 Sequence *seq;
254
255 if (scene->id.tag & LIB_TAG_DOIT) {
256 return;
257 }
258 scene->id.tag |= LIB_TAG_DOIT;
259
260 SEQ_ALL_BEGIN (scene->ed, seq) {
261 BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_fn, scene);
262 }
263 SEQ_ALL_END;
264
265 fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
266 if (fcu || driven) {
267 scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
268 }
269 else {
270 scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED;
271 }
272 }
273
sound_update_animation_flags_exec(bContext * C,wmOperator * UNUSED (op))274 static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op))
275 {
276 Scene *scene = CTX_data_scene(C);
277
278 BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false);
279 sound_update_animation_flags(CTX_data_scene(C));
280 DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
281 return OPERATOR_FINISHED;
282 }
283
SOUND_OT_update_animation_flags(wmOperatorType * ot)284 static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
285 {
286 /*
287 * This operator is needed to set a correct state of the sound animation
288 * System. Unfortunately there's no really correct place to call the exec
289 * function, that's why I made it an operator that's only visible in the
290 * search menu. Apart from that the bake animation operator calls it too.
291 */
292
293 /* identifiers */
294 ot->name = "Update Animation";
295 ot->description = "Update animation flags";
296 ot->idname = "SOUND_OT_update_animation_flags";
297
298 /* api callbacks */
299 ot->exec = sound_update_animation_flags_exec;
300
301 /* flags */
302 ot->flag = OPTYPE_REGISTER;
303 }
304
305 /* ******************************************************* */
306
sound_bake_animation_exec(bContext * C,wmOperator * UNUSED (op))307 static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
308 {
309 Scene *scene = CTX_data_scene(C);
310 /* NOTE: We will be forcefully evaluating dependency graph at every frame, so no need to ensure
311 * current scene state is evaluated as it will be lost anyway. */
312 struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
313 int oldfra = scene->r.cfra;
314 int cfra;
315
316 sound_update_animation_flags_exec(C, NULL);
317
318 for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
319 scene->r.cfra = cfra;
320 BKE_scene_graph_update_for_newframe(depsgraph);
321 }
322
323 scene->r.cfra = oldfra;
324 BKE_scene_graph_update_for_newframe(depsgraph);
325
326 return OPERATOR_FINISHED;
327 }
328
SOUND_OT_bake_animation(wmOperatorType * ot)329 static void SOUND_OT_bake_animation(wmOperatorType *ot)
330 {
331 /* identifiers */
332 ot->name = "Update Animation Cache";
333 ot->description = "Update the audio animation cache";
334 ot->idname = "SOUND_OT_bake_animation";
335
336 /* api callbacks */
337 ot->exec = sound_bake_animation_exec;
338
339 /* flags */
340 ot->flag = OPTYPE_REGISTER;
341 }
342
343 /******************** mixdown operator ********************/
344
sound_mixdown_exec(bContext * C,wmOperator * op)345 static int sound_mixdown_exec(bContext *C, wmOperator *op)
346 {
347 #ifdef WITH_AUDASPACE
348 char path[FILE_MAX];
349 char filename[FILE_MAX];
350 Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
351 Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
352 Main *bmain = CTX_data_main(C);
353 int split;
354
355 int bitrate, accuracy;
356 AUD_DeviceSpecs specs;
357 AUD_Container container;
358 AUD_Codec codec;
359 const char *result;
360
361 sound_bake_animation_exec(C, op);
362
363 RNA_string_get(op->ptr, "filepath", path);
364 bitrate = RNA_int_get(op->ptr, "bitrate") * 1000;
365 accuracy = RNA_int_get(op->ptr, "accuracy");
366 specs.format = RNA_enum_get(op->ptr, "format");
367 container = RNA_enum_get(op->ptr, "container");
368 codec = RNA_enum_get(op->ptr, "codec");
369 split = RNA_boolean_get(op->ptr, "split_channels");
370 specs.channels = scene_eval->r.ffcodecdata.audio_channels;
371 specs.rate = scene_eval->r.ffcodecdata.audio_mixrate;
372
373 BLI_strncpy(filename, path, sizeof(filename));
374 BLI_path_abs(filename, BKE_main_blendfile_path(bmain));
375
376 const double fps = (((double)scene_eval->r.frs_sec) / (double)scene_eval->r.frs_sec_base);
377 const int start_frame = scene_eval->r.sfra;
378 const int end_frame = scene_eval->r.efra;
379
380 if (split) {
381 result = AUD_mixdown_per_channel(scene_eval->sound_scene,
382 start_frame * specs.rate / fps,
383 (end_frame - start_frame + 1) * specs.rate / fps,
384 accuracy,
385 filename,
386 specs,
387 container,
388 codec,
389 bitrate,
390 NULL,
391 NULL);
392 }
393 else {
394 result = AUD_mixdown(scene_eval->sound_scene,
395 start_frame * specs.rate / fps,
396 (end_frame - start_frame + 1) * specs.rate / fps,
397 accuracy,
398 filename,
399 specs,
400 container,
401 codec,
402 bitrate,
403 NULL,
404 NULL);
405 }
406
407 BKE_sound_reset_scene_specs(scene_eval);
408
409 if (result) {
410 BKE_report(op->reports, RPT_ERROR, result);
411 return OPERATOR_CANCELLED;
412 }
413 #else /* WITH_AUDASPACE */
414 (void)C;
415 (void)op;
416 #endif /* WITH_AUDASPACE */
417 return OPERATOR_FINISHED;
418 }
419
420 #ifdef WITH_AUDASPACE
421 static const EnumPropertyItem container_items[] = {
422 # ifdef WITH_FFMPEG
423 {AUD_CONTAINER_AC3, "AC3", 0, "ac3", "Dolby Digital ATRAC 3"},
424 # endif
425 {AUD_CONTAINER_FLAC, "FLAC", 0, "flac", "Free Lossless Audio Codec"},
426 # ifdef WITH_FFMPEG
427 {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "mkv", "Matroska"},
428 {AUD_CONTAINER_MP2, "MP2", 0, "mp2", "MPEG-1 Audio Layer II"},
429 {AUD_CONTAINER_MP3, "MP3", 0, "mp3", "MPEG-2 Audio Layer III"},
430 # endif
431 {AUD_CONTAINER_OGG, "OGG", 0, "ogg", "Xiph.Org Ogg Container"},
432 {AUD_CONTAINER_WAV, "WAV", 0, "wav", "Waveform Audio File Format"},
433 {0, NULL, 0, NULL, NULL},
434 };
435
436 static const char *snd_ext_sound[] = {
437 ".ac3",
438 ".flac",
439 ".mkv",
440 ".mp2",
441 ".mp3",
442 ".ogg",
443 ".wav",
444 NULL,
445 };
446
sound_mixdown_check(bContext * UNUSED (C),wmOperator * op)447 static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
448 {
449 AUD_Container container = RNA_enum_get(op->ptr, "container");
450
451 const char *extension = NULL;
452
453 const EnumPropertyItem *item = container_items;
454 while (item->identifier != NULL) {
455 if (item->value == container) {
456 const char **ext = snd_ext_sound;
457 while (*ext != NULL) {
458 if (STREQ(*ext + 1, item->name)) {
459 extension = *ext;
460 break;
461 }
462
463 ext++;
464 }
465 }
466 item++;
467 }
468
469 if (extension) {
470 PropertyRNA *prop;
471 char filepath[FILE_MAX];
472
473 int check;
474
475 prop = RNA_struct_find_property(op->ptr, "filepath");
476 RNA_property_string_get(op->ptr, prop, filepath);
477
478 if (BLI_path_extension_check_array(filepath, snd_ext_sound)) {
479 check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
480 }
481 else {
482 check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
483 }
484
485 if (!check) {
486 return check;
487 }
488
489 RNA_property_string_set(op->ptr, prop, filepath);
490 return true;
491 }
492
493 return false;
494 }
495
496 #endif /* WITH_AUDASPACE */
497
sound_mixdown_invoke(bContext * C,wmOperator * op,const wmEvent * event)498 static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
499 {
500 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
501 return sound_mixdown_exec(C, op);
502 }
503
504 return WM_operator_filesel(C, op, event);
505 }
506
507 #ifdef WITH_AUDASPACE
508
sound_mixdown_draw_check_prop(PointerRNA * UNUSED (ptr),PropertyRNA * prop,void * UNUSED (user_data))509 static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr),
510 PropertyRNA *prop,
511 void *UNUSED(user_data))
512 {
513 const char *prop_id = RNA_property_identifier(prop);
514 return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
515 STREQ(prop_id, "filename"));
516 }
517
sound_mixdown_draw(bContext * C,wmOperator * op)518 static void sound_mixdown_draw(bContext *C, wmOperator *op)
519 {
520 static const EnumPropertyItem pcm_format_items[] = {
521 {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
522 {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
523 # ifdef WITH_SNDFILE
524 {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
525 # endif
526 {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
527 {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
528 {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
529 {0, NULL, 0, NULL, NULL},
530 };
531
532 static const EnumPropertyItem mp3_format_items[] = {
533 {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
534 {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
535 {0, NULL, 0, NULL, NULL},
536 };
537
538 # ifdef WITH_SNDFILE
539 static const EnumPropertyItem flac_format_items[] = {
540 {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
541 {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
542 {0, NULL, 0, NULL, NULL},
543 };
544 # endif
545
546 static const EnumPropertyItem all_codec_items[] = {
547 {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
548 {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
549 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
550 {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
551 {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
552 {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
553 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
554 {0, NULL, 0, NULL, NULL},
555 };
556
557 static const EnumPropertyItem ogg_codec_items[] = {
558 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
559 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
560 {0, NULL, 0, NULL, NULL},
561 };
562
563 uiLayout *layout = op->layout;
564 wmWindowManager *wm = CTX_wm_manager(C);
565 PointerRNA ptr;
566 PropertyRNA *prop_format;
567 PropertyRNA *prop_codec;
568 PropertyRNA *prop_bitrate;
569
570 uiLayoutSetPropSep(layout, true);
571 uiLayoutSetPropDecorate(layout, false);
572
573 AUD_Container container = RNA_enum_get(op->ptr, "container");
574 AUD_Codec codec = RNA_enum_get(op->ptr, "codec");
575
576 prop_format = RNA_struct_find_property(op->ptr, "format");
577 prop_codec = RNA_struct_find_property(op->ptr, "codec");
578 prop_bitrate = RNA_struct_find_property(op->ptr, "bitrate");
579
580 RNA_def_property_clear_flag(prop_bitrate, PROP_HIDDEN);
581 RNA_def_property_flag(prop_codec, PROP_HIDDEN);
582 RNA_def_property_flag(prop_format, PROP_HIDDEN);
583
584 switch (container) {
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
595 RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
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:
602 RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
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);
621 RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
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);
626 RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
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:
642 RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
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:
648 RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
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);
654 RNA_def_property_clear_flag(prop_format, 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
663 RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
664
665 /* main draw call */
666 uiDefAutoButsRNA(
667 layout, &ptr, sound_mixdown_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
668 }
669 #endif /* WITH_AUDASPACE */
670
SOUND_OT_mixdown(wmOperatorType * ot)671 static void SOUND_OT_mixdown(wmOperatorType *ot)
672 {
673 #ifdef WITH_AUDASPACE
674 static const EnumPropertyItem format_items[] = {
675 {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
676 {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
677 {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
678 {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
679 {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
680 {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
681 {0, NULL, 0, NULL, NULL},
682 };
683
684 static const EnumPropertyItem codec_items[] = {
685 # ifdef WITH_FFMPEG
686 {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
687 {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
688 # endif
689 {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
690 # ifdef WITH_FFMPEG
691 {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
692 {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
693 # endif
694 {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
695 {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
696 {0, NULL, 0, NULL, NULL},
697 };
698
699 #endif /* WITH_AUDASPACE */
700
701 /* identifiers */
702 ot->name = "Mixdown";
703 ot->description = "Mix the scene's audio to a sound file";
704 ot->idname = "SOUND_OT_mixdown";
705
706 /* api callbacks */
707 ot->exec = sound_mixdown_exec;
708 ot->invoke = sound_mixdown_invoke;
709
710 #ifdef WITH_AUDASPACE
711 ot->check = sound_mixdown_check;
712 ot->ui = sound_mixdown_draw;
713 #endif
714 /* flags */
715 ot->flag = OPTYPE_REGISTER;
716
717 /* properties */
718 WM_operator_properties_filesel(ot,
719 FILE_TYPE_FOLDER | FILE_TYPE_SOUND,
720 FILE_SPECIAL,
721 FILE_SAVE,
722 WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
723 FILE_DEFAULTDISPLAY,
724 FILE_SORT_ALPHA);
725 #ifdef WITH_AUDASPACE
726 RNA_def_int(
727 ot->srna,
728 "accuracy",
729 1024,
730 1,
731 16777216,
732 "Accuracy",
733 "Sample accuracy, important for animation data (the lower the value, the more accurate)",
734 1,
735 16777216);
736 RNA_def_enum(
737 ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
738 RNA_def_enum(ot->srna, "codec", codec_items, AUD_CODEC_FLAC, "Codec", "Audio Codec");
739 RNA_def_enum(ot->srna, "format", format_items, AUD_FORMAT_S16, "Format", "Sample format");
740 RNA_def_int(ot->srna, "bitrate", 192, 32, 512, "Bitrate", "Bitrate in kbit/s", 32, 512);
741 RNA_def_boolean(ot->srna,
742 "split_channels",
743 0,
744 "Split channels",
745 "Each channel will be rendered into a mono file");
746 #endif /* WITH_AUDASPACE */
747 }
748
749 /* ******************************************************* */
750
sound_poll(bContext * C)751 static bool sound_poll(bContext *C)
752 {
753 Editing *ed = CTX_data_scene(C)->ed;
754
755 if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
756 return false;
757 }
758
759 return true;
760 }
761 /********************* pack operator *********************/
762
sound_pack_exec(bContext * C,wmOperator * op)763 static int sound_pack_exec(bContext *C, wmOperator *op)
764 {
765 Main *bmain = CTX_data_main(C);
766 Editing *ed = CTX_data_scene(C)->ed;
767 bSound *sound;
768
769 if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
770 return OPERATOR_CANCELLED;
771 }
772
773 sound = ed->act_seq->sound;
774
775 if (!sound || sound->packedfile) {
776 return OPERATOR_CANCELLED;
777 }
778
779 sound->packedfile = BKE_packedfile_new(
780 op->reports, sound->filepath, ID_BLEND_PATH(bmain, &sound->id));
781 BKE_sound_load(bmain, sound);
782
783 return OPERATOR_FINISHED;
784 }
785
SOUND_OT_pack(wmOperatorType * ot)786 static void SOUND_OT_pack(wmOperatorType *ot)
787 {
788 /* identifiers */
789 ot->name = "Pack Sound";
790 ot->description = "Pack the sound into the current blend file";
791 ot->idname = "SOUND_OT_pack";
792
793 /* api callbacks */
794 ot->exec = sound_pack_exec;
795 ot->poll = sound_poll;
796
797 /* flags */
798 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
799 }
800
801 /********************* unpack operator *********************/
802
sound_unpack_exec(bContext * C,wmOperator * op)803 static int sound_unpack_exec(bContext *C, wmOperator *op)
804 {
805 Main *bmain = CTX_data_main(C);
806 int method = RNA_enum_get(op->ptr, "method");
807 bSound *sound = NULL;
808
809 /* find the supplied image by name */
810 if (RNA_struct_property_is_set(op->ptr, "id")) {
811 char sndname[MAX_ID_NAME - 2];
812 RNA_string_get(op->ptr, "id", sndname);
813 sound = BLI_findstring(&bmain->sounds, sndname, offsetof(ID, name) + 2);
814 }
815
816 if (!sound || !sound->packedfile) {
817 return OPERATOR_CANCELLED;
818 }
819
820 if (G.fileflags & G_FILE_AUTOPACK) {
821 BKE_report(op->reports,
822 RPT_WARNING,
823 "AutoPack is enabled, so image will be packed again on file save");
824 }
825
826 BKE_packedfile_unpack_sound(bmain, op->reports, sound, method);
827
828 return OPERATOR_FINISHED;
829 }
830
sound_unpack_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))831 static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
832 {
833 Editing *ed = CTX_data_scene(C)->ed;
834 bSound *sound;
835
836 if (RNA_struct_property_is_set(op->ptr, "id")) {
837 return sound_unpack_exec(C, op);
838 }
839
840 if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
841 return OPERATOR_CANCELLED;
842 }
843
844 sound = ed->act_seq->sound;
845
846 if (!sound || !sound->packedfile) {
847 return OPERATOR_CANCELLED;
848 }
849
850 if (G.fileflags & G_FILE_AUTOPACK) {
851 BKE_report(op->reports,
852 RPT_WARNING,
853 "AutoPack is enabled, so image will be packed again on file save");
854 }
855
856 unpack_menu(
857 C, "SOUND_OT_unpack", sound->id.name + 2, sound->filepath, "sounds", sound->packedfile);
858
859 return OPERATOR_FINISHED;
860 }
861
SOUND_OT_unpack(wmOperatorType * ot)862 static void SOUND_OT_unpack(wmOperatorType *ot)
863 {
864 /* identifiers */
865 ot->name = "Unpack Sound";
866 ot->description = "Unpack the sound to the samples filename";
867 ot->idname = "SOUND_OT_unpack";
868
869 /* api callbacks */
870 ot->exec = sound_unpack_exec;
871 ot->invoke = sound_unpack_invoke;
872 ot->poll = sound_poll;
873
874 /* flags */
875 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
876
877 /* properties */
878 RNA_def_enum(
879 ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
880 /* XXX, weark!, will fail with library, name collisions */
881 RNA_def_string(
882 ot->srna, "id", NULL, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack");
883 }
884
885 /* ******************************************************* */
886
ED_operatortypes_sound(void)887 void ED_operatortypes_sound(void)
888 {
889 WM_operatortype_append(SOUND_OT_open);
890 WM_operatortype_append(SOUND_OT_open_mono);
891 WM_operatortype_append(SOUND_OT_mixdown);
892 WM_operatortype_append(SOUND_OT_pack);
893 WM_operatortype_append(SOUND_OT_unpack);
894 WM_operatortype_append(SOUND_OT_update_animation_flags);
895 WM_operatortype_append(SOUND_OT_bake_animation);
896 }
897