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