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