CMake: add WITH_LINKER_LLD option for unix platforms
[blender-staging.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_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
72 static void sound_open_cancel(bContext *UNUSED(C), wmOperator *op)
73 {
74   MEM_freeN(op->customdata);
75   op->customdata = NULL;
76 }
77
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
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
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
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
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
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
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
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_BEGIN (scene->ed, seq) {
261     BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_fn, scene);
262   }
263   SEQ_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
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
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
307 static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
308 {
309   Main *bmain = CTX_data_main(C);
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, bmain);
322   }
323
324   scene->r.cfra = oldfra;
325   BKE_scene_graph_update_for_newframe(depsgraph, bmain);
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   }
392   else {
393     result = AUD_mixdown(scene_eval->sound_scene,
394                          start_frame * specs.rate / fps,
395                          (end_frame - start_frame + 1) * specs.rate / fps,
396                          accuracy,
397                          filename,
398                          specs,
399                          container,
400                          codec,
401                          bitrate);
402   }
403
404   BKE_sound_reset_scene_specs(scene_eval);
405
406   if (result) {
407     BKE_report(op->reports, RPT_ERROR, result);
408     return OPERATOR_CANCELLED;
409   }
410 #else   // WITH_AUDASPACE
411   (void)C;
412   (void)op;
413 #endif  // WITH_AUDASPACE
414   return OPERATOR_FINISHED;
415 }
416
417 #ifdef WITH_AUDASPACE
418 static const EnumPropertyItem container_items[] = {
419 #  ifdef WITH_FFMPEG
420     {AUD_CONTAINER_AC3, "AC3", 0, "ac3", "Dolby Digital ATRAC 3"},
421 #  endif
422     {AUD_CONTAINER_FLAC, "FLAC", 0, "flac", "Free Lossless Audio Codec"},
423 #  ifdef WITH_FFMPEG
424     {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "mkv", "Matroska"},
425     {AUD_CONTAINER_MP2, "MP2", 0, "mp2", "MPEG-1 Audio Layer II"},
426     {AUD_CONTAINER_MP3, "MP3", 0, "mp3", "MPEG-2 Audio Layer III"},
427 #  endif
428     {AUD_CONTAINER_OGG, "OGG", 0, "ogg", "Xiph.Org Ogg Container"},
429     {AUD_CONTAINER_WAV, "WAV", 0, "wav", "Waveform Audio File Format"},
430     {0, NULL, 0, NULL, NULL},
431 };
432
433 static const char *snd_ext_sound[] = {
434     ".ac3",
435     ".flac",
436     ".mkv",
437     ".mp2",
438     ".mp3",
439     ".ogg",
440     ".wav",
441     NULL,
442 };
443
444 static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
445 {
446   AUD_Container container = RNA_enum_get(op->ptr, "container");
447
448   const char *extension = NULL;
449
450   const EnumPropertyItem *item = container_items;
451   while (item->identifier != NULL) {
452     if (item->value == container) {
453       const char **ext = snd_ext_sound;
454       while (*ext != NULL) {
455         if (STREQ(*ext + 1, item->name)) {
456           extension = *ext;
457           break;
458         }
459
460         ext++;
461       }
462     }
463     item++;
464   }
465
466   if (extension) {
467     PropertyRNA *prop;
468     char filepath[FILE_MAX];
469
470     int check;
471
472     prop = RNA_struct_find_property(op->ptr, "filepath");
473     RNA_property_string_get(op->ptr, prop, filepath);
474
475     if (BLI_path_extension_check_array(filepath, snd_ext_sound)) {
476       check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
477     }
478     else {
479       check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
480     }
481
482     if (!check) {
483       return check;
484     }
485
486     RNA_property_string_set(op->ptr, prop, filepath);
487     return true;
488   }
489
490   return false;
491 }
492
493 #endif  // WITH_AUDASPACE
494
495 static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
496 {
497   if (RNA_struct_property_is_set(op->ptr, "filepath")) {
498     return sound_mixdown_exec(C, op);
499   }
500
501   return WM_operator_filesel(C, op, event);
502 }
503
504 #ifdef WITH_AUDASPACE
505
506 static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr),
507                                           PropertyRNA *prop,
508                                           void *UNUSED(user_data))
509 {
510   const char *prop_id = RNA_property_identifier(prop);
511   return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
512            STREQ(prop_id, "filename"));
513 }
514
515 static void sound_mixdown_draw(bContext *C, wmOperator *op)
516 {
517   static const EnumPropertyItem pcm_format_items[] = {
518       {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
519       {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
520 #  ifdef WITH_SNDFILE
521       {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
522 #  endif
523       {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
524       {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
525       {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
526       {0, NULL, 0, NULL, NULL},
527   };
528
529   static const EnumPropertyItem mp3_format_items[] = {
530       {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
531       {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
532       {0, NULL, 0, NULL, NULL},
533   };
534
535 #  ifdef WITH_SNDFILE
536   static const EnumPropertyItem flac_format_items[] = {
537       {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
538       {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
539       {0, NULL, 0, NULL, NULL},
540   };
541 #  endif
542
543   static const EnumPropertyItem all_codec_items[] = {
544       {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
545       {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
546       {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
547       {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
548       {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
549       {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
550       {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
551       {0, NULL, 0, NULL, NULL},
552   };
553
554   static const EnumPropertyItem ogg_codec_items[] = {
555       {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
556       {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
557       {0, NULL, 0, NULL, NULL},
558   };
559
560   uiLayout *layout = op->layout;
561   wmWindowManager *wm = CTX_wm_manager(C);
562   PointerRNA ptr;
563   PropertyRNA *prop_format;
564   PropertyRNA *prop_codec;
565   PropertyRNA *prop_bitrate;
566
567   AUD_Container container = RNA_enum_get(op->ptr, "container");
568   AUD_Codec codec = RNA_enum_get(op->ptr, "codec");
569
570   prop_format = RNA_struct_find_property(op->ptr, "format");
571   prop_codec = RNA_struct_find_property(op->ptr, "codec");
572   prop_bitrate = RNA_struct_find_property(op->ptr, "bitrate");
573
574   RNA_def_property_clear_flag(prop_bitrate, PROP_HIDDEN);
575   RNA_def_property_flag(prop_codec, PROP_HIDDEN);
576   RNA_def_property_flag(prop_format, PROP_HIDDEN);
577
578   switch (container) {
579     case AUD_CONTAINER_AC3:
580       RNA_def_property_enum_items(prop_codec, all_codec_items);
581       RNA_enum_set(op->ptr, "codec", AUD_CODEC_AC3);
582       RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
583       break;
584     case AUD_CONTAINER_FLAC:
585       RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
586       RNA_def_property_enum_items(prop_codec, all_codec_items);
587       RNA_enum_set(op->ptr, "codec", AUD_CODEC_FLAC);
588 #  ifdef WITH_SNDFILE
589       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
590       RNA_def_property_enum_items(prop_format, flac_format_items);
591 #  else
592       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
593 #  endif
594       break;
595     case AUD_CONTAINER_MATROSKA:
596       RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
597       RNA_def_property_enum_items(prop_codec, all_codec_items);
598
599       switch (codec) {
600         case AUD_CODEC_AAC:
601           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
602           break;
603         case AUD_CODEC_AC3:
604           RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
605           break;
606         case AUD_CODEC_FLAC:
607           RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
608           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
609           break;
610         case AUD_CODEC_MP2:
611           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
612           break;
613         case AUD_CODEC_MP3:
614           RNA_def_property_enum_items(prop_format, mp3_format_items);
615           RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
616           break;
617         case AUD_CODEC_PCM:
618           RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
619           RNA_def_property_enum_items(prop_format, pcm_format_items);
620           RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
621           break;
622         case AUD_CODEC_VORBIS:
623           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
624           break;
625         default:
626           break;
627       }
628
629       break;
630     case AUD_CONTAINER_MP2:
631       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
632       RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP2);
633       RNA_def_property_enum_items(prop_codec, all_codec_items);
634       break;
635     case AUD_CONTAINER_MP3:
636       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
637       RNA_def_property_enum_items(prop_format, mp3_format_items);
638       RNA_def_property_enum_items(prop_codec, all_codec_items);
639       RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP3);
640       break;
641     case AUD_CONTAINER_OGG:
642       RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
643       RNA_def_property_enum_items(prop_codec, ogg_codec_items);
644       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
645       break;
646     case AUD_CONTAINER_WAV:
647       RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
648       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
649       RNA_def_property_enum_items(prop_format, pcm_format_items);
650       RNA_def_property_enum_items(prop_codec, all_codec_items);
651       RNA_enum_set(op->ptr, "codec", AUD_CODEC_PCM);
652       break;
653     default:
654       break;
655   }
656
657   RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
658
659   /* main draw call */
660   uiDefAutoButsRNA(
661       layout, &ptr, sound_mixdown_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
662 }
663 #endif  // WITH_AUDASPACE
664
665 static void SOUND_OT_mixdown(wmOperatorType *ot)
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, NULL, 0, NULL, NULL},
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, NULL, 0, NULL, NULL},
691   };
692
693 #endif  // WITH_AUDASPACE
694
695   /* identifiers */
696   ot->name = "Mixdown";
697   ot->description = "Mix the scene's audio to a sound file";
698   ot->idname = "SOUND_OT_mixdown";
699
700   /* api callbacks */
701   ot->exec = sound_mixdown_exec;
702   ot->invoke = sound_mixdown_invoke;
703
704 #ifdef WITH_AUDASPACE
705   ot->check = sound_mixdown_check;
706   ot->ui = sound_mixdown_draw;
707 #endif
708   /* flags */
709   ot->flag = OPTYPE_REGISTER;
710
711   /* properties */
712   WM_operator_properties_filesel(ot,
713                                  FILE_TYPE_FOLDER | FILE_TYPE_SOUND,
714                                  FILE_SPECIAL,
715                                  FILE_SAVE,
716                                  WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
717                                  FILE_DEFAULTDISPLAY,
718                                  FILE_SORT_ALPHA);
719 #ifdef WITH_AUDASPACE
720   RNA_def_int(
721       ot->srna,
722       "accuracy",
723       1024,
724       1,
725       16777216,
726       "Accuracy",
727       "Sample accuracy, important for animation data (the lower the value, the more accurate)",
728       1,
729       16777216);
730   RNA_def_enum(
731       ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
732   RNA_def_enum(ot->srna, "codec", codec_items, AUD_CODEC_FLAC, "Codec", "Audio Codec");
733   RNA_def_enum(ot->srna, "format", format_items, AUD_FORMAT_S16, "Format", "Sample format");
734   RNA_def_int(ot->srna, "bitrate", 192, 32, 512, "Bitrate", "Bitrate in kbit/s", 32, 512);
735   RNA_def_boolean(ot->srna,
736                   "split_channels",
737                   0,
738                   "Split channels",
739                   "Each channel will be rendered into a mono file");
740 #endif  // WITH_AUDASPACE
741 }
742
743 /* ******************************************************* */
744
745 static bool sound_poll(bContext *C)
746 {
747   Editing *ed = CTX_data_scene(C)->ed;
748
749   if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
750     return 0;
751   }
752
753   return 1;
754 }
755 /********************* pack operator *********************/
756
757 static int sound_pack_exec(bContext *C, wmOperator *op)
758 {
759   Main *bmain = CTX_data_main(C);
760   Editing *ed = CTX_data_scene(C)->ed;
761   bSound *sound;
762
763   if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
764     return OPERATOR_CANCELLED;
765   }
766
767   sound = ed->act_seq->sound;
768
769   if (!sound || sound->packedfile) {
770     return OPERATOR_CANCELLED;
771   }
772
773   sound->packedfile = BKE_packedfile_new(
774       op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
775   BKE_sound_load(bmain, sound);
776
777   return OPERATOR_FINISHED;
778 }
779
780 static void SOUND_OT_pack(wmOperatorType *ot)
781 {
782   /* identifiers */
783   ot->name = "Pack Sound";
784   ot->description = "Pack the sound into the current blend file";
785   ot->idname = "SOUND_OT_pack";
786
787   /* api callbacks */
788   ot->exec = sound_pack_exec;
789   ot->poll = sound_poll;
790
791   /* flags */
792   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
793 }
794
795 /********************* unpack operator *********************/
796
797 static int sound_unpack_exec(bContext *C, wmOperator *op)
798 {
799   Main *bmain = CTX_data_main(C);
800   int method = RNA_enum_get(op->ptr, "method");
801   bSound *sound = NULL;
802
803   /* find the supplied image by name */
804   if (RNA_struct_property_is_set(op->ptr, "id")) {
805     char sndname[MAX_ID_NAME - 2];
806     RNA_string_get(op->ptr, "id", sndname);
807     sound = BLI_findstring(&bmain->sounds, sndname, offsetof(ID, name) + 2);
808   }
809
810   if (!sound || !sound->packedfile) {
811     return OPERATOR_CANCELLED;
812   }
813
814   if (G.fileflags & G_FILE_AUTOPACK) {
815     BKE_report(op->reports,
816                RPT_WARNING,
817                "AutoPack is enabled, so image will be packed again on file save");
818   }
819
820   BKE_packedfile_unpack_sound(bmain, op->reports, sound, method);
821
822   return OPERATOR_FINISHED;
823 }
824
825 static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
826 {
827   Editing *ed = CTX_data_scene(C)->ed;
828   bSound *sound;
829
830   if (RNA_struct_property_is_set(op->ptr, "id")) {
831     return sound_unpack_exec(C, op);
832   }
833
834   if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) {
835     return OPERATOR_CANCELLED;
836   }
837
838   sound = ed->act_seq->sound;
839
840   if (!sound || !sound->packedfile) {
841     return OPERATOR_CANCELLED;
842   }
843
844   if (G.fileflags & G_FILE_AUTOPACK) {
845     BKE_report(op->reports,
846                RPT_WARNING,
847                "AutoPack is enabled, so image will be packed again on file save");
848   }
849
850   unpack_menu(C, "SOUND_OT_unpack", sound->id.name + 2, sound->name, "sounds", sound->packedfile);
851
852   return OPERATOR_FINISHED;
853 }
854
855 static void SOUND_OT_unpack(wmOperatorType *ot)
856 {
857   /* identifiers */
858   ot->name = "Unpack Sound";
859   ot->description = "Unpack the sound to the samples filename";
860   ot->idname = "SOUND_OT_unpack";
861
862   /* api callbacks */
863   ot->exec = sound_unpack_exec;
864   ot->invoke = sound_unpack_invoke;
865   ot->poll = sound_poll;
866
867   /* flags */
868   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
869
870   /* properties */
871   RNA_def_enum(
872       ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
873   /* XXX, weark!, will fail with library, name collisions */
874   RNA_def_string(
875       ot->srna, "id", NULL, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack");
876 }
877
878 /* ******************************************************* */
879
880 void ED_operatortypes_sound(void)
881 {
882   WM_operatortype_append(SOUND_OT_open);
883   WM_operatortype_append(SOUND_OT_open_mono);
884   WM_operatortype_append(SOUND_OT_mixdown);
885   WM_operatortype_append(SOUND_OT_pack);
886   WM_operatortype_append(SOUND_OT_unpack);
887   WM_operatortype_append(SOUND_OT_update_animation_flags);
888   WM_operatortype_append(SOUND_OT_bake_animation);
889 }