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