Merge branch 'blender2.7'
[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 <string.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <stddef.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_space_types.h"
37 #include "DNA_sequence_types.h"
38 #include "DNA_sound_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_library.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 "ED_sound.h"
66 #include "ED_util.h"
67
68 /******************** open sound operator ********************/
69
70 static void sound_open_cancel(bContext *UNUSED(C), wmOperator *op)
71 {
72   MEM_freeN(op->customdata);
73   op->customdata = NULL;
74 }
75
76 static void sound_open_init(bContext *C, wmOperator *op)
77 {
78   PropertyPointerRNA *pprop;
79
80   op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
81   UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
82 }
83
84 #ifdef WITH_AUDASPACE
85 static int sound_open_exec(bContext *C, wmOperator *op)
86 {
87   char path[FILE_MAX];
88   bSound *sound;
89   PropertyPointerRNA *pprop;
90   PointerRNA idptr;
91   AUD_SoundInfo info;
92   Main *bmain = CTX_data_main(C);
93
94   RNA_string_get(op->ptr, "filepath", path);
95   sound = BKE_sound_new_file(bmain, path);
96
97   if (!op->customdata)
98     sound_open_init(C, op);
99
100   if (sound->playback_handle == NULL) {
101     if (op->customdata)
102       MEM_freeN(op->customdata);
103     BKE_id_free(bmain, sound);
104     BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
105     return OPERATOR_CANCELLED;
106   }
107
108   info = AUD_getInfo(sound->playback_handle);
109
110   if (info.specs.channels == AUD_CHANNELS_INVALID) {
111     BKE_id_free(bmain, sound);
112     if (op->customdata)
113       MEM_freeN(op->customdata);
114     BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
115     return OPERATOR_CANCELLED;
116   }
117
118   if (RNA_boolean_get(op->ptr, "mono")) {
119     sound->flags |= SOUND_FLAGS_MONO;
120     BKE_sound_load(bmain, sound);
121   }
122
123   if (RNA_boolean_get(op->ptr, "cache")) {
124     BKE_sound_cache(sound);
125   }
126
127   /* hook into UI */
128   pprop = op->customdata;
129
130   if (pprop->prop) {
131     /* when creating new ID blocks, use is already 1, but RNA
132      * pointer use also increases user, so this compensates it */
133     id_us_min(&sound->id);
134
135     RNA_id_pointer_create(&sound->id, &idptr);
136     RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
137     RNA_property_update(C, &pprop->ptr, pprop->prop);
138   }
139
140   MEM_freeN(op->customdata);
141   return OPERATOR_FINISHED;
142 }
143
144 #else  //WITH_AUDASPACE
145
146 static int sound_open_exec(bContext *UNUSED(C), wmOperator *op)
147 {
148   BKE_report(op->reports, RPT_ERROR, "Compiled without sound support");
149
150   return OPERATOR_CANCELLED;
151 }
152
153 #endif
154
155 static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
156 {
157   if (RNA_struct_property_is_set(op->ptr, "filepath"))
158     return sound_open_exec(C, op);
159
160   sound_open_init(C, op);
161
162   return WM_operator_filesel(C, op, event);
163 }
164
165 static void SOUND_OT_open(wmOperatorType *ot)
166 {
167   /* identifiers */
168   ot->name = "Open Sound";
169   ot->description = "Load a sound file";
170   ot->idname = "SOUND_OT_open";
171
172   /* api callbacks */
173   ot->exec = sound_open_exec;
174   ot->invoke = sound_open_invoke;
175   ot->cancel = sound_open_cancel;
176
177   /* flags */
178   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
179
180   /* properties */
181   WM_operator_properties_filesel(ot,
182                                  FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
183                                  FILE_SPECIAL,
184                                  FILE_OPENFILE,
185                                  WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
186                                  FILE_DEFAULTDISPLAY,
187                                  FILE_SORT_ALPHA);
188   RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
189   RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one");
190 }
191
192 static void SOUND_OT_open_mono(wmOperatorType *ot)
193 {
194   /* identifiers */
195   ot->name = "Open Sound Mono";
196   ot->description = "Load a sound file as mono";
197   ot->idname = "SOUND_OT_open_mono";
198
199   /* api callbacks */
200   ot->exec = sound_open_exec;
201   ot->invoke = sound_open_invoke;
202   ot->cancel = sound_open_cancel;
203
204   /* flags */
205   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
206
207   /* properties */
208   WM_operator_properties_filesel(ot,
209                                  FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
210                                  FILE_SPECIAL,
211                                  FILE_OPENFILE,
212                                  WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
213                                  FILE_DEFAULTDISPLAY,
214                                  FILE_SORT_ALPHA);
215   RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
216   RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono");
217 }
218
219 /* ******************************************************* */
220
221 static void sound_update_animation_flags(Scene *scene);
222
223 static int sound_update_animation_flags_cb(Sequence *seq, void *user_data)
224 {
225   struct FCurve *fcu;
226   Scene *scene = (Scene *)user_data;
227   bool driven;
228
229   fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven);
230   if (fcu || driven)
231     seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED;
232   else
233     seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED;
234
235   fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven);
236   if (fcu || driven)
237     seq->flag |= SEQ_AUDIO_PITCH_ANIMATED;
238   else
239     seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED;
240
241   fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven);
242   if (fcu || driven)
243     seq->flag |= SEQ_AUDIO_PAN_ANIMATED;
244   else
245     seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED;
246
247   if (seq->type == SEQ_TYPE_SCENE) {
248     /* TODO(sergey): For now we do manual recursion into the scene strips,
249      * but perhaps it should be covered by recursive_apply?
250      */
251     sound_update_animation_flags(seq->scene);
252   }
253
254   return 0;
255 }
256
257 static void sound_update_animation_flags(Scene *scene)
258 {
259   struct FCurve *fcu;
260   bool driven;
261   Sequence *seq;
262
263   if (scene->id.tag & LIB_TAG_DOIT) {
264     return;
265   }
266   scene->id.tag |= LIB_TAG_DOIT;
267
268   SEQ_BEGIN (scene->ed, seq) {
269     BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_cb, scene);
270   }
271   SEQ_END;
272
273   fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
274   if (fcu || driven)
275     scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
276   else
277     scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED;
278 }
279
280 static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op))
281 {
282   BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false);
283   sound_update_animation_flags(CTX_data_scene(C));
284   return OPERATOR_FINISHED;
285 }
286
287 static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
288 {
289   /*
290    * This operator is needed to set a correct state of the sound animation
291    * System. Unfortunately there's no really correct place to call the exec
292    * function, that's why I made it an operator that's only visible in the
293    * search menu. Apart from that the bake animation operator calls it too.
294    */
295
296   /* identifiers */
297   ot->name = "Update Animation";
298   ot->description = "Update animation flags";
299   ot->idname = "SOUND_OT_update_animation_flags";
300
301   /* api callbacks */
302   ot->exec = sound_update_animation_flags_exec;
303
304   /* flags */
305   ot->flag = OPTYPE_REGISTER;
306 }
307
308 /* ******************************************************* */
309
310 static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
311 {
312   Main *bmain = CTX_data_main(C);
313   Scene *scene = CTX_data_scene(C);
314   struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
315   int oldfra = scene->r.cfra;
316   int cfra;
317
318   sound_update_animation_flags_exec(C, NULL);
319
320   for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
321     scene->r.cfra = cfra;
322     BKE_scene_graph_update_for_newframe(depsgraph, bmain);
323   }
324
325   scene->r.cfra = oldfra;
326   BKE_scene_graph_update_for_newframe(depsgraph, bmain);
327
328   return OPERATOR_FINISHED;
329 }
330
331 static void SOUND_OT_bake_animation(wmOperatorType *ot)
332 {
333   /* identifiers */
334   ot->name = "Update Animation Cache";
335   ot->description = "Update the audio animation cache";
336   ot->idname = "SOUND_OT_bake_animation";
337
338   /* api callbacks */
339   ot->exec = sound_bake_animation_exec;
340
341   /* flags */
342   ot->flag = OPTYPE_REGISTER;
343 }
344
345 /******************** mixdown operator ********************/
346
347 static int sound_mixdown_exec(bContext *C, wmOperator *op)
348 {
349 #ifdef WITH_AUDASPACE
350   char path[FILE_MAX];
351   char filename[FILE_MAX];
352   Scene *scene;
353   Main *bmain;
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   scene = CTX_data_scene(C);
372   bmain = CTX_data_main(C);
373   specs.channels = scene->r.ffcodecdata.audio_channels;
374   specs.rate = scene->r.ffcodecdata.audio_mixrate;
375
376   BLI_strncpy(filename, path, sizeof(filename));
377   BLI_path_abs(filename, BKE_main_blendfile_path(bmain));
378
379   if (split)
380     result = AUD_mixdown_per_channel(scene->sound_scene,
381                                      SFRA * specs.rate / FPS,
382                                      (EFRA - SFRA + 1) * specs.rate / FPS,
383                                      accuracy,
384                                      filename,
385                                      specs,
386                                      container,
387                                      codec,
388                                      bitrate);
389   else
390     result = AUD_mixdown(scene->sound_scene,
391                          SFRA * specs.rate / FPS,
392                          (EFRA - SFRA + 1) * specs.rate / FPS,
393                          accuracy,
394                          filename,
395                          specs,
396                          container,
397                          codec,
398                          bitrate);
399
400   BKE_sound_reset_scene_specs(scene);
401
402   if (result) {
403     BKE_report(op->reports, RPT_ERROR, result);
404     return OPERATOR_CANCELLED;
405   }
406 #else   // WITH_AUDASPACE
407   (void)C;
408   (void)op;
409 #endif  // WITH_AUDASPACE
410   return OPERATOR_FINISHED;
411 }
412
413 #ifdef WITH_AUDASPACE
414 static const EnumPropertyItem container_items[] = {
415 #  ifdef WITH_FFMPEG
416     {AUD_CONTAINER_AC3, "AC3", 0, "ac3", "Dolby Digital ATRAC 3"},
417 #  endif
418     {AUD_CONTAINER_FLAC, "FLAC", 0, "flac", "Free Lossless Audio Codec"},
419 #  ifdef WITH_FFMPEG
420     {AUD_CONTAINER_MATROSKA, "MATROSKA", 0, "mkv", "Matroska"},
421     {AUD_CONTAINER_MP2, "MP2", 0, "mp2", "MPEG-1 Audio Layer II"},
422     {AUD_CONTAINER_MP3, "MP3", 0, "mp3", "MPEG-2 Audio Layer III"},
423 #  endif
424     {AUD_CONTAINER_OGG, "OGG", 0, "ogg", "Xiph.Org Ogg Container"},
425     {AUD_CONTAINER_WAV, "WAV", 0, "wav", "Waveform Audio File Format"},
426     {0, NULL, 0, NULL, NULL},
427 };
428
429 static const char *snd_ext_sound[] = {
430     ".ac3",
431     ".flac",
432     ".mkv",
433     ".mp2",
434     ".mp3",
435     ".ogg",
436     ".wav",
437     NULL,
438 };
439
440 static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
441 {
442   AUD_Container container = RNA_enum_get(op->ptr, "container");
443
444   const char *extension = NULL;
445
446   const EnumPropertyItem *item = container_items;
447   while (item->identifier != NULL) {
448     if (item->value == container) {
449       const char **ext = snd_ext_sound;
450       while (*ext != NULL) {
451         if (STREQ(*ext + 1, item->name)) {
452           extension = *ext;
453           break;
454         }
455
456         ext++;
457       }
458     }
459     item++;
460   }
461
462   if (extension) {
463     PropertyRNA *prop;
464     char filepath[FILE_MAX];
465
466     int check;
467
468     prop = RNA_struct_find_property(op->ptr, "filepath");
469     RNA_property_string_get(op->ptr, prop, filepath);
470
471     if (BLI_path_extension_check_array(filepath, snd_ext_sound))
472       check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
473     else
474       check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
475
476     if (!check)
477       return check;
478
479     RNA_property_string_set(op->ptr, prop, filepath);
480     return true;
481   }
482
483   return false;
484 }
485
486 #endif  // WITH_AUDASPACE
487
488 static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
489 {
490   if (RNA_struct_property_is_set(op->ptr, "filepath"))
491     return sound_mixdown_exec(C, op);
492
493   return WM_operator_filesel(C, op, event);
494 }
495
496 #ifdef WITH_AUDASPACE
497
498 static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr),
499                                           PropertyRNA *prop,
500                                           void *UNUSED(user_data))
501 {
502   const char *prop_id = RNA_property_identifier(prop);
503   return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
504            STREQ(prop_id, "filename"));
505 }
506
507 static void sound_mixdown_draw(bContext *C, wmOperator *op)
508 {
509   static const EnumPropertyItem pcm_format_items[] = {
510       {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
511       {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
512 #  ifdef WITH_SNDFILE
513       {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
514 #  endif
515       {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
516       {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
517       {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
518       {0, NULL, 0, NULL, NULL},
519   };
520
521   static const EnumPropertyItem mp3_format_items[] = {
522       {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
523       {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
524       {0, NULL, 0, NULL, NULL},
525   };
526
527 #  ifdef WITH_SNDFILE
528   static const EnumPropertyItem flac_format_items[] = {
529       {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
530       {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
531       {0, NULL, 0, NULL, NULL},
532   };
533 #  endif
534
535   static const EnumPropertyItem all_codec_items[] = {
536       {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
537       {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
538       {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
539       {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
540       {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
541       {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
542       {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
543       {0, NULL, 0, NULL, NULL},
544   };
545
546   static const EnumPropertyItem ogg_codec_items[] = {
547       {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
548       {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
549       {0, NULL, 0, NULL, NULL},
550   };
551
552   uiLayout *layout = op->layout;
553   wmWindowManager *wm = CTX_wm_manager(C);
554   PointerRNA ptr;
555   PropertyRNA *prop_format;
556   PropertyRNA *prop_codec;
557   PropertyRNA *prop_bitrate;
558
559   AUD_Container container = RNA_enum_get(op->ptr, "container");
560   AUD_Codec codec = RNA_enum_get(op->ptr, "codec");
561
562   prop_format = RNA_struct_find_property(op->ptr, "format");
563   prop_codec = RNA_struct_find_property(op->ptr, "codec");
564   prop_bitrate = RNA_struct_find_property(op->ptr, "bitrate");
565
566   RNA_def_property_clear_flag(prop_bitrate, PROP_HIDDEN);
567   RNA_def_property_flag(prop_codec, PROP_HIDDEN);
568   RNA_def_property_flag(prop_format, PROP_HIDDEN);
569
570   switch (container) {
571     case AUD_CONTAINER_AC3:
572       RNA_def_property_enum_items(prop_codec, all_codec_items);
573       RNA_enum_set(op->ptr, "codec", AUD_CODEC_AC3);
574       RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
575       break;
576     case AUD_CONTAINER_FLAC:
577       RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
578       RNA_def_property_enum_items(prop_codec, all_codec_items);
579       RNA_enum_set(op->ptr, "codec", AUD_CODEC_FLAC);
580 #  ifdef WITH_SNDFILE
581       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
582       RNA_def_property_enum_items(prop_format, flac_format_items);
583 #  else
584       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
585 #  endif
586       break;
587     case AUD_CONTAINER_MATROSKA:
588       RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
589       RNA_def_property_enum_items(prop_codec, all_codec_items);
590
591       switch (codec) {
592         case AUD_CODEC_AAC:
593           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
594           break;
595         case AUD_CODEC_AC3:
596           RNA_enum_set(op->ptr, "format", AUD_FORMAT_FLOAT32);
597           break;
598         case AUD_CODEC_FLAC:
599           RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
600           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
601           break;
602         case AUD_CODEC_MP2:
603           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
604           break;
605         case AUD_CODEC_MP3:
606           RNA_def_property_enum_items(prop_format, mp3_format_items);
607           RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
608           break;
609         case AUD_CODEC_PCM:
610           RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
611           RNA_def_property_enum_items(prop_format, pcm_format_items);
612           RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
613           break;
614         case AUD_CODEC_VORBIS:
615           RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
616           break;
617         default:
618           break;
619       }
620
621       break;
622     case AUD_CONTAINER_MP2:
623       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
624       RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP2);
625       RNA_def_property_enum_items(prop_codec, all_codec_items);
626       break;
627     case AUD_CONTAINER_MP3:
628       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
629       RNA_def_property_enum_items(prop_format, mp3_format_items);
630       RNA_def_property_enum_items(prop_codec, all_codec_items);
631       RNA_enum_set(op->ptr, "codec", AUD_CODEC_MP3);
632       break;
633     case AUD_CONTAINER_OGG:
634       RNA_def_property_clear_flag(prop_codec, PROP_HIDDEN);
635       RNA_def_property_enum_items(prop_codec, ogg_codec_items);
636       RNA_enum_set(op->ptr, "format", AUD_FORMAT_S16);
637       break;
638     case AUD_CONTAINER_WAV:
639       RNA_def_property_flag(prop_bitrate, PROP_HIDDEN);
640       RNA_def_property_clear_flag(prop_format, PROP_HIDDEN);
641       RNA_def_property_enum_items(prop_format, pcm_format_items);
642       RNA_def_property_enum_items(prop_codec, all_codec_items);
643       RNA_enum_set(op->ptr, "codec", AUD_CODEC_PCM);
644       break;
645     default:
646       break;
647   }
648
649   RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
650
651   /* main draw call */
652   uiDefAutoButsRNA(
653       layout, &ptr, sound_mixdown_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
654 }
655 #endif  // WITH_AUDASPACE
656
657 static void SOUND_OT_mixdown(wmOperatorType *ot)
658 {
659 #ifdef WITH_AUDASPACE
660   static const EnumPropertyItem format_items[] = {
661       {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"},
662       {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"},
663       {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"},
664       {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"},
665       {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"},
666       {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"},
667       {0, NULL, 0, NULL, NULL},
668   };
669
670   static const EnumPropertyItem codec_items[] = {
671 #  ifdef WITH_FFMPEG
672       {AUD_CODEC_AAC, "AAC", 0, "AAC", "Advanced Audio Coding"},
673       {AUD_CODEC_AC3, "AC3", 0, "AC3", "Dolby Digital ATRAC 3"},
674 #  endif
675       {AUD_CODEC_FLAC, "FLAC", 0, "FLAC", "Free Lossless Audio Codec"},
676 #  ifdef WITH_FFMPEG
677       {AUD_CODEC_MP2, "MP2", 0, "MP2", "MPEG-1 Audio Layer II"},
678       {AUD_CODEC_MP3, "MP3", 0, "MP3", "MPEG-2 Audio Layer III"},
679 #  endif
680       {AUD_CODEC_PCM, "PCM", 0, "PCM", "Pulse Code Modulation (RAW)"},
681       {AUD_CODEC_VORBIS, "VORBIS", 0, "Vorbis", "Xiph.Org Vorbis Codec"},
682       {0, NULL, 0, NULL, NULL},
683   };
684
685 #endif  // WITH_AUDASPACE
686
687   /* identifiers */
688   ot->name = "Mixdown";
689   ot->description = "Mix the scene's audio to a sound file";
690   ot->idname = "SOUND_OT_mixdown";
691
692   /* api callbacks */
693   ot->exec = sound_mixdown_exec;
694   ot->invoke = sound_mixdown_invoke;
695
696 #ifdef WITH_AUDASPACE
697   ot->check = sound_mixdown_check;
698   ot->ui = sound_mixdown_draw;
699 #endif
700   /* flags */
701   ot->flag = OPTYPE_REGISTER;
702
703   /* properties */
704   WM_operator_properties_filesel(ot,
705                                  FILE_TYPE_FOLDER | FILE_TYPE_SOUND,
706                                  FILE_SPECIAL,
707                                  FILE_SAVE,
708                                  WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
709                                  FILE_DEFAULTDISPLAY,
710                                  FILE_SORT_ALPHA);
711 #ifdef WITH_AUDASPACE
712   RNA_def_int(
713       ot->srna,
714       "accuracy",
715       1024,
716       1,
717       16777216,
718       "Accuracy",
719       "Sample accuracy, important for animation data (the lower the value, the more accurate)",
720       1,
721       16777216);
722   RNA_def_enum(
723       ot->srna, "container", container_items, AUD_CONTAINER_FLAC, "Container", "File format");
724   RNA_def_enum(ot->srna, "codec", codec_items, AUD_CODEC_FLAC, "Codec", "Audio Codec");
725   RNA_def_enum(ot->srna, "format", format_items, AUD_FORMAT_S16, "Format", "Sample format");
726   RNA_def_int(ot->srna, "bitrate", 192, 32, 512, "Bitrate", "Bitrate in kbit/s", 32, 512);
727   RNA_def_boolean(ot->srna,
728                   "split_channels",
729                   0,
730                   "Split channels",
731                   "Each channel will be rendered into a mono file");
732 #endif  // WITH_AUDASPACE
733 }
734
735 /* ******************************************************* */
736
737 static bool sound_poll(bContext *C)
738 {
739   Editing *ed = CTX_data_scene(C)->ed;
740
741   if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
742     return 0;
743
744   return 1;
745 }
746 /********************* pack operator *********************/
747
748 static int sound_pack_exec(bContext *C, wmOperator *op)
749 {
750   Main *bmain = CTX_data_main(C);
751   Editing *ed = CTX_data_scene(C)->ed;
752   bSound *sound;
753
754   if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
755     return OPERATOR_CANCELLED;
756
757   sound = ed->act_seq->sound;
758
759   if (!sound || sound->packedfile)
760     return OPERATOR_CANCELLED;
761
762   sound->packedfile = newPackedFile(op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
763   BKE_sound_load(bmain, sound);
764
765   return OPERATOR_FINISHED;
766 }
767
768 static void SOUND_OT_pack(wmOperatorType *ot)
769 {
770   /* identifiers */
771   ot->name = "Pack Sound";
772   ot->description = "Pack the sound into the current blend file";
773   ot->idname = "SOUND_OT_pack";
774
775   /* api callbacks */
776   ot->exec = sound_pack_exec;
777   ot->poll = sound_poll;
778
779   /* flags */
780   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
781 }
782
783 /********************* unpack operator *********************/
784
785 static int sound_unpack_exec(bContext *C, wmOperator *op)
786 {
787   Main *bmain = CTX_data_main(C);
788   int method = RNA_enum_get(op->ptr, "method");
789   bSound *sound = NULL;
790
791   /* find the suppplied image by name */
792   if (RNA_struct_property_is_set(op->ptr, "id")) {
793     char sndname[MAX_ID_NAME - 2];
794     RNA_string_get(op->ptr, "id", sndname);
795     sound = BLI_findstring(&bmain->sounds, sndname, offsetof(ID, name) + 2);
796   }
797
798   if (!sound || !sound->packedfile)
799     return OPERATOR_CANCELLED;
800
801   if (G.fileflags & G_FILE_AUTOPACK)
802     BKE_report(op->reports,
803                RPT_WARNING,
804                "AutoPack is enabled, so image will be packed again on file save");
805
806   unpackSound(bmain, op->reports, sound, method);
807
808   return OPERATOR_FINISHED;
809 }
810
811 static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
812 {
813   Editing *ed = CTX_data_scene(C)->ed;
814   bSound *sound;
815
816   if (RNA_struct_property_is_set(op->ptr, "id"))
817     return sound_unpack_exec(C, op);
818
819   if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM)
820     return OPERATOR_CANCELLED;
821
822   sound = ed->act_seq->sound;
823
824   if (!sound || !sound->packedfile)
825     return OPERATOR_CANCELLED;
826
827   if (G.fileflags & G_FILE_AUTOPACK)
828     BKE_report(op->reports,
829                RPT_WARNING,
830                "AutoPack is enabled, so image will be packed again on file save");
831
832   unpack_menu(C, "SOUND_OT_unpack", sound->id.name + 2, sound->name, "sounds", sound->packedfile);
833
834   return OPERATOR_FINISHED;
835 }
836
837 static void SOUND_OT_unpack(wmOperatorType *ot)
838 {
839   /* identifiers */
840   ot->name = "Unpack Sound";
841   ot->description = "Unpack the sound to the samples filename";
842   ot->idname = "SOUND_OT_unpack";
843
844   /* api callbacks */
845   ot->exec = sound_unpack_exec;
846   ot->invoke = sound_unpack_invoke;
847   ot->poll = sound_poll;
848
849   /* flags */
850   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
851
852   /* properties */
853   RNA_def_enum(
854       ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack");
855   /* XXX, weark!, will fail with library, name collisions */
856   RNA_def_string(
857       ot->srna, "id", NULL, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack");
858 }
859
860 /* ******************************************************* */
861
862 void ED_operatortypes_sound(void)
863 {
864   WM_operatortype_append(SOUND_OT_open);
865   WM_operatortype_append(SOUND_OT_open_mono);
866   WM_operatortype_append(SOUND_OT_mixdown);
867   WM_operatortype_append(SOUND_OT_pack);
868   WM_operatortype_append(SOUND_OT_unpack);
869   WM_operatortype_append(SOUND_OT_update_animation_flags);
870   WM_operatortype_append(SOUND_OT_bake_animation);
871 }