004fb33f0dd32b48c4a538fdda9536e958f5b303
[blender.git] / source / blender / editors / sound / sound_ops.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stddef.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_blenlib.h"
37 #include "BLI_utildefines.h"
38
39 #include "DNA_packedFile_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_sequence_types.h"
43 #include "DNA_sound_types.h"
44 #include "DNA_userdef_types.h"
45
46 #include "BKE_context.h"
47 #include "BKE_global.h"
48 #include "BKE_main.h"
49 #include "BKE_report.h"
50 #include "BKE_packedFile.h"
51 #include "BKE_sound.h"
52
53 #include "RNA_access.h"
54 #include "RNA_define.h"
55 #include "RNA_enum_types.h"
56
57 #include "UI_interface.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61
62 #include "AUD_C-API.h"
63
64 #include "ED_util.h"
65
66 #include "sound_intern.h"
67
68 /******************** open sound operator ********************/
69
70 static void open_init(bContext *C, wmOperator *op)
71 {
72         PropertyPointerRNA *pprop;
73         
74         op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
75         uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
76 }
77
78 static int open_exec(bContext *C, wmOperator *op)
79 {
80         char path[FILE_MAX];
81         bSound *sound;
82         PropertyPointerRNA *pprop;
83         PointerRNA idptr;
84         AUD_SoundInfo info;
85
86         RNA_string_get(op->ptr, "filepath", path);
87         sound = sound_new_file(CTX_data_main(C), path);
88
89         if(!op->customdata)
90                 open_init(C, op);
91         
92         if (sound==NULL || sound->playback_handle == NULL) {
93                 if(op->customdata) MEM_freeN(op->customdata);
94                 BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
95                 return OPERATOR_CANCELLED;
96         }
97
98         info = AUD_getInfo(sound->playback_handle);
99
100         if (info.specs.channels == AUD_CHANNELS_INVALID) {
101                 sound_delete(C, sound);
102                 if(op->customdata) MEM_freeN(op->customdata);
103                 BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
104                 return OPERATOR_CANCELLED;
105         }
106
107         if (RNA_boolean_get(op->ptr, "cache")) {
108                 sound_cache(sound, 0);
109         }
110         
111         /* hook into UI */
112         pprop= op->customdata;
113         
114         if(pprop->prop) {
115                 /* when creating new ID blocks, use is already 1, but RNA
116                  * pointer se also increases user, so this compensates it */
117                 sound->id.us--;
118                 
119                 RNA_id_pointer_create(&sound->id, &idptr);
120                 RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
121                 RNA_property_update(C, &pprop->ptr, pprop->prop);
122         }
123
124         if(op->customdata) MEM_freeN(op->customdata);
125         return OPERATOR_FINISHED;
126 }
127
128 static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
129 {
130         if(!RNA_property_is_set(op->ptr, "relative_path"))
131                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
132         
133         if(RNA_property_is_set(op->ptr, "filepath"))
134                 return open_exec(C, op);
135         
136         open_init(C, op);
137         
138         return WM_operator_filesel(C, op, event);
139 }
140
141 void SOUND_OT_open(wmOperatorType *ot)
142 {
143         /* identifiers */
144         ot->name= "Open Sound";
145         ot->description= "Load a sound file";
146         ot->idname= "SOUND_OT_open";
147
148         /* api callbacks */
149         ot->exec= open_exec;
150         ot->invoke= open_invoke;
151
152         /* flags */
153         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
154
155         /* properties */
156         WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE|MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH);
157         RNA_def_boolean(ot->srna, "cache", FALSE, "Cache", "Cache the sound in memory.");
158 }
159
160 /* ******************************************************* */
161
162 static int sound_poll(bContext *C)
163 {
164         Editing* ed = CTX_data_scene(C)->ed;
165
166         if(!ed || !ed->act_seq || ed->act_seq->type != SEQ_SOUND)
167                 return 0;
168
169         return 1;
170 }
171 /********************* pack operator *********************/
172
173 static int pack_exec(bContext *C, wmOperator *op)
174 {
175         Editing* ed = CTX_data_scene(C)->ed;
176         bSound* sound;
177
178         if(!ed || !ed->act_seq || ed->act_seq->type != SEQ_SOUND)
179                 return OPERATOR_CANCELLED;
180
181         sound = ed->act_seq->sound;
182
183         if(!sound || sound->packedfile)
184                 return OPERATOR_CANCELLED;
185
186         sound->packedfile= newPackedFile(op->reports, sound->name);
187         sound_load(CTX_data_main(C), sound);
188
189         return OPERATOR_FINISHED;
190 }
191
192 void SOUND_OT_pack(wmOperatorType *ot)
193 {
194         /* identifiers */
195         ot->name= "Pack Sound";
196         ot->description= "Pack the sound into the current blend file";
197         ot->idname= "SOUND_OT_pack";
198
199         /* api callbacks */
200         ot->exec= pack_exec;
201         ot->poll= sound_poll;
202
203         /* flags */
204         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
205 }
206
207 /********************* unpack operator *********************/
208
209 static int sound_unpack_exec(bContext *C, wmOperator *op)
210 {
211         int method= RNA_enum_get(op->ptr, "method");
212         bSound* sound;
213
214         /* find the suppplied image by name */
215         if (RNA_property_is_set(op->ptr, "id")) {
216                 char sndname[22];
217                 RNA_string_get(op->ptr, "id", sndname);
218                 sound = BLI_findstring(&CTX_data_main(C)->sound, sndname, offsetof(ID, name) + 2);
219         }
220
221         if(!sound || !sound->packedfile)
222                 return OPERATOR_CANCELLED;
223
224         if(G.fileflags & G_AUTOPACK)
225                 BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save.");
226
227         unpackSound(CTX_data_main(C), op->reports, sound, method);
228
229         return OPERATOR_FINISHED;
230 }
231
232 static int sound_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
233 {
234         Editing* ed = CTX_data_scene(C)->ed;
235         bSound* sound;
236
237         if(RNA_property_is_set(op->ptr, "id"))
238                 return sound_unpack_exec(C, op);
239
240         if(!ed || !ed->act_seq || ed->act_seq->type != SEQ_SOUND)
241                 return OPERATOR_CANCELLED;
242
243         sound = ed->act_seq->sound;
244
245         if(!sound || !sound->packedfile)
246                 return OPERATOR_CANCELLED;
247
248         if(G.fileflags & G_AUTOPACK)
249                 BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save.");
250
251         unpack_menu(C, "SOUND_OT_unpack", sound->id.name+2, sound->name, "audio", sound->packedfile);
252
253         return OPERATOR_FINISHED;
254 }
255
256 void SOUND_OT_unpack(wmOperatorType *ot)
257 {
258         /* identifiers */
259         ot->name= "Unpack Sound";
260         ot->description= "Unpack the sound to the samples filename";
261         ot->idname= "SOUND_OT_unpack";
262
263         /* api callbacks */
264         ot->exec= sound_unpack_exec;
265         ot->invoke= sound_unpack_invoke;
266         ot->poll= sound_poll;
267
268         /* flags */
269         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
270
271         /* properties */
272         RNA_def_enum(ot->srna, "method", unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack.");
273         RNA_def_string(ot->srna, "id", "", 21, "Sound Name", "Sound datablock name to unpack."); /* XXX, weark!, will fail with library, name collisions */
274 }
275
276 /* ******************************************************* */
277
278 void ED_operatortypes_sound(void)
279 {
280         WM_operatortype_append(SOUND_OT_open);
281         WM_operatortype_append(SOUND_OT_pack);
282         WM_operatortype_append(SOUND_OT_unpack);
283 }