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