Merge branch 'blender-v2.92-release'
[blender.git] / source / blender / editors / sound / sound_ops.c
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_sound.h"
50
51 #include "RNA_access.h"
52 #include "RNA_define.h"
53 #include "RNA_enum_types.h"
54
55 #include "SEQ_iterator.h"
56
57 #include "UI_interface.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61
62 #ifdef WITH_AUDASPACE
63 #  include <AUD_Special.h>
64 #endif
65
66 #include "DEG_depsgraph_query.h"
67
68 #include "ED_sound.h"
69 #include "ED_util.h"
70
71 /******************** open sound operator ********************/
72
73 static void sound_open_cancel(bContext *UNUSED(C), wmOperator *op)
74 {
75   MEM_freeN(op->customdata);
76   op->customdata = NULL;
77 }
78
79 static void sound_open_init(bContext *C, wmOperator *op)
80 {
81   PropertyPointerRNA *pprop;
82
83   op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
84   UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
85 }
86
87 #ifdef WITH_AUDASPACE
88 static int sound_open_exec(bContext *C, wmOperator *op)
89 {
90   char path[FILE_MAX];
91   bSound *sound;
92   PropertyPointerRNA *pprop;
93   PointerRNA idptr;
94   Main *bmain = CTX_data_main(C);
95
96   RNA_string_get(op->ptr, "filepath", path);
97   sound = BKE_sound_new_file(bmain, path);
98
99   if (!op->customdata) {
100     sound_open_init(C, op);
101   }
102
103   if (RNA_boolean_get(op->ptr, "mono")) {
104     sound->flags |= SOUND_FLAGS_MONO;
105   }
106
107   if (RNA_boolean_get(op->ptr, "cache")) {
108     sound->flags |= SOUND_FLAGS_CACHING;
109   }
110
111   /* hook into UI */
112   pprop = op->customdata;
113
114   if (pprop->prop) {
115     /* when creating new ID blocks, use is already 1, but RNA
116      * pointer use also increases user, so this compensates it */
117     id_us_min(&sound->id);
118
119     RNA_id_pointer_create(&sound->id, &idptr);
120     RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
121     RNA_property_update(C, &pprop->ptr, pprop->prop);
122   }
123
124   DEG_relations_tag_update(bmain);
125
126   MEM_freeN(op->customdata);
127   return OPERATOR_FINISHED;
128 }
129
130 #else /* WITH_AUDASPACE */
131
132 static int sound_open_exec(bContext *UNUSED(C), wmOperator *op)
133 {
134   BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
135
136   return OPERATOR_CANCELLED;
137 }
138
139 #endif
140
141 static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
142 {
143   if (RNA_struct_property_is_set(op->ptr, "filepath")) {
144     return sound_open_exec(C, op);
145   }
146
147   sound_open_init(C, op);
148
149   return WM_operator_filesel(C, op, event);
150 }
151
152 static void SOUND_OT_open(wmOperatorType *ot)
153 {
154   /* identifiers */
155   ot->name = "Open Sound";
156   ot->description = "Load a sound file";
157   ot->idname = "SOUND_OT_open";
158
159   /* api callbacks */
160   ot->exec = sound_open_exec;
161   ot->invoke = sound_open_invoke;
162   ot->cancel = sound_open_cancel;
163
164   /* flags */
165   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
166
167   /* properties */
168   WM_operator_properties_filesel(ot,
169                                  FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
170                                  FILE_SPECIAL,
171                                  FILE_OPENFILE,
172                                  WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
173                                  FILE_DEFAULTDISPLAY,
174                                  FILE_SORT_DEFAULT);
175   RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
176   RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
177 }
178
179 static void SOUND_OT_open_mono(wmOperatorType *ot)
180 {
181   /* identifiers */
182   ot->name = "Open Sound Mono";
183   ot->description = "Load a sound file as mono";
184   ot->idname = "SOUND_OT_open_mono";
185
186   /* api callbacks */
187   ot->exec = sound_open_exec;
188   ot->invoke = sound_open_invoke;
189   ot->cancel = sound_open_cancel;
190
191   /* flags */
192   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
193
194   /* properties */
195   WM_operator_properties_filesel(ot,
196                                  FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
197                                  FILE_SPECIAL,
198                                  FILE_OPENFILE,
199                                  WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
200                                  FILE_DEFAULTDISPLAY,
201                                  FILE_SORT_DEFAULT);
202   RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
203   RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
204 }
205
206 /* ******************************************************* */
207
208 static void sound_update_animation_flags(Scene *scene);
209
210 static int sound_update_animation_flags_fn(Sequence *seq, void *user_data)
211 {
212   struct FCurve *fcu;
213   Scene *scene = (Scene *)user_data;
214   bool driven;
215
216   fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven);
217   if (fcu || driven) {
218     seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED;
219   }
220   else {
221     seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED;
222   }
223
224   fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven);
225   if (fcu || driven) {
226     seq->flag |= SEQ_AUDIO_PITCH_ANIMATED;
227   }
228   else {
229     seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED;
230   }
231
232   fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven);
233   if (fcu || driven) {
234     seq->flag |= SEQ_AUDIO_PAN_ANIMATED;
235   }
236   else {
237     seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED;
238   }
239
240   if (seq->type == SEQ_TYPE_SCENE) {
241     /* TODO(sergey): For now we do manual recursion into the scene strips,
242      * but perhaps it should be covered by recursive_apply?
243      */
244     sound_update_animation_flags(seq->scene);
245   }
246
247   return 0;
248 }
249
250 static void sound_update_animation_flags(Scene *scene)
251 {
252   struct FCurve *fcu;
253   bool driven;
254   Sequence *seq;
255
256   if (scene->id.tag & LIB_TAG_DOIT) {
257     return;
258   }
259   scene->id.tag |= LIB_TAG_DOIT;
260
261   SEQ_ALL_BEGIN (scene->ed, seq) {
262     SEQ_iterator_recursive_apply(seq, sound_update_animation_flags_fn, scene);
263   }
264   SEQ_ALL_END;
265
266   fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
267   if (fcu || driven) {
268     scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
269   }
270   else {
271     scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED;
272   }
273 }
274
275 static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op))
276 {
277   Scene *scene = CTX_data_scene(C);
278
279   BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false);
280   sound_update_animation_flags(CTX_data_scene(C));
281   DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
282   return OPERATOR_FINISHED;
283 }
284
285 static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
286 {
287   /*
288    * This operator is needed to set a correct state of the sound animation
289    * System. Unfortunately there's no really correct place to call the exec
290    * function, that's why I made it an operator that's only visible in the
291    * search menu. Apart from that the bake animation operator calls it too.
292    */
293
294   /* identifiers */
295   ot->name = "Update Animation";
296   ot->description = "Update animation flags";
297   ot->idname = "SOUND_OT_update_animation_flags";
298
299   /* api callbacks */
300   ot->exec = sound_update_animation_flags_exec;
301
302   /* flags */
303   ot->flag = OPTYPE_REGISTER;
304 }
305
306 /* ******************************************************* */
307
308 static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
309 {
310   Scene *scene = CTX_data_scene(C);
311   /* NOTE: We will be forcefully evaluating dependency graph at every frame, so no need to ensure
312    * current scene state is evaluated as it will be lost anyway. */
313   struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
314   int oldfra = scene->r.cfra;
315   int cfra;
316
317   sound_update_animation_flags_exec(C, NULL);
318
319   for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
320     scene->r.cfra = cfra;
321     BKE_scene_graph_update_for_newframe(depsgraph);
322   }
323
324   scene->r.cfra = oldfra;
325   BKE_scene_graph_update_for_newframe(depsgraph);
326
327   return OPERATOR_FINISHED;
328 }
329
330 static void SOUND_OT_bake_animation(wmOperatorType *ot)
331 {
332   /* identifiers */
333   ot->name = "Update Animation Cache";
334   ot->description = "Update the audio animation cache";
335   ot->idname = "SOUND_OT_bake_animation";
336
337   /* api callbacks */
338   ot->exec = sound_bake_animation_exec;
339
340   /* flags */
341   ot->flag = OPTYPE_REGISTER;
342 }
343
344 /******************** mixdown operator ********************/
345
346 static int sound_mixdown_exec(bContext *C, wmOperator *op)
347 {
348 #ifdef WITH_AUDASPACE
349   char path[FILE_MAX];
350   char filename[FILE_MAX];
351   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
352   Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
353   Main *bmain = CTX_data_main(C);
354   int split;
355
356   int bitrate, accuracy;
357   AUD_DeviceSpecs specs;
358   AUD_Container container;
359   AUD_Codec codec;
360   const char *result;
361
362   sound_bake_animation_exec(C, op);
363
364   RNA_string_get(op->ptr, "filepath", path);
365   bitrate = RNA_int_get(op->ptr, "bitrate") * 1000;
366   accuracy = RNA_int_get(op->ptr, "accuracy");
367   specs.format = RNA_enum_get(op->ptr, "format");
368   container = RNA_enum_get(op->ptr, "container");
369   codec = RNA_enum_get(op->ptr, "codec");
370   split = RNA_boolean_get(op->ptr, "split_channels");
371   specs.channels = scene_eval->r.ffcodecdata.audio_channels;
372   specs.rate = scene_eval->r.ffcodecdata.audio_mixrate;
373
374   BLI_strncpy(filename, path, sizeof(filename));
375   BLI_path_abs(filename, BKE_main_blendfile_path(bmain));
376
377   const double fps = (((double)scene_eval->r.frs_sec) / (double)scene_eval->r.frs_sec_base);
378   const int start_frame = scene_eval->r.sfra;
379   const int end_frame = scene_eval->r.efra;
380
381   if (split) {
382     result = AUD_mixdown_per_channel(scene_eval->sound_scene,
383                                      start_frame * specs.rate / fps,
384                                      (end_frame - start_frame + 1) * specs.rate / fps,
385                                      accuracy,
386                                      filename,
387                                      specs,
388                                      container,
389                                      codec,
390                                      bitrate,
391                                      NULL,
392                                      NULL);
393   }
394   else {
395     result = AUD_mixdown(scene_eval->sound_scene,
396                          start_frame * specs.rate / fps,
397                          (end_frame - start_frame + 1) * specs.rate / fps,
398                          accuracy,
399                          filename,
400                          specs,
401                          container,
402                          codec,
403                          bitrate,
404                          NULL,
405                          NULL);
406   }
407
408   BKE_sound_reset_scene_specs(scene_eval);
409
410   if (result) {
411     BKE_report(op->reports, RPT_ERROR, result);
412     return OPERATOR_CANCELLED;
413   }
414 #else  /* WITH_AUDASPACE */
415   (void)C;
416   (void)op;
417 #endif /* WITH_AUDASPACE */
418   return OPERATOR_FINISHED;
419 }
420
421 #ifdef WITH_AUDASPACE
422 static const EnumPropertyItem container_items[] = {
423 #  ifdef WITH_FFMPEG
424     {AUD_CONTAINER_AC3, "AC3", 0, "ac3", "Dolby Digital ATRAC 3"},
425 #  endif
426     {AUD_CONTAINER_FLAC, "FLAC", 0, "flac", "Free Lossless Audio Codec"},
427 #  ifdef WITH_FFMPEG
428     {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "mkv", "Matroska"},
429     {AUD_CONTAINER_MP2, "MP2", 0, "mp2", "MPEG-1 Audio Layer II"},
430     {AUD_CONTAINER_MP3, "MP3", 0, "mp3", "MPEG-2 Audio Layer III"},
431 #  endif
432     {AUD_CONTAINER_OGG, "OGG", 0, "ogg", "Xiph.Org Ogg Container"},
433     {AUD_CONTAINER_WAV, "WAV", 0, "wav", "Waveform Audio File Format"},
434     {0, NULL, 0, NULL, NULL},
435 };
436
437 static const char *snd_ext_sound[] = {
438     ".ac3",
439     ".flac",
440     ".mkv",
441     ".mp2",
442     ".mp3",
443     ".ogg",
444     ".wav",
445     NULL,
446 };
447
448 static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
449 {
450   AUD_Container container = RNA_enum_get(op->ptr, "container");
451
452   const char *extension = NULL;
453
454   const EnumPropertyItem *item = container_items;
455   while (item->identifier != NULL) {
456     if (item->value == container) {
457       const char **ext = snd_ext_sound;
458       while (*ext != NULL) {
459         if (STREQ(*ext + 1, item->name)) {
460           extension = *ext;
461           break;
462         }
463
464         ext++;
465       }
466     }
467     item++;
468   }
469
470   if (extension) {
471     PropertyRNA *prop;
472     char filepath[FILE_MAX];
473
474     int check;
475
476     prop = RNA_struct_find_property(op->ptr, "filepath");
477     RNA_property_string_get(op->ptr, prop, filepath);
478
479     if (BLI_path_extension_check_array(filepath, snd_ext_sound)) {
480       check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
481     }
482     else {
483       check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
484     }
485
486     if (!check) {
487       return check;
488     }
489
490     RNA_property_string_set(op->ptr, prop, filepath);
491     return true;
492   }
493
494   return false;
495 }
496
497 #endif /* WITH_AUDASPACE */
498
499 static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
500 {
501   if (RNA_struct_property_is_set(op->ptr, "filepath")) {
502     return sound_mixdown_exec(C, op);
503   }
504
505   return WM_operator_filesel(C, op, event);
506 }
507
508 #ifdef WITH_AUDASPACE
509
510 static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr),
511                                           PropertyRNA *prop,
512                                           void *UNUSED(user_data))
513 {
514   const char *prop_id = RNA_property_identifier(prop);
515   return !(STR_ELEM(prop_id, "filepath", "directory", "filename"));
516 }
517
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
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_DEFAULT);
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
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
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
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
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
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
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
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 }