Fix for [#22741] Material preview doesn't update when "undo" is used to revert a...
[blender.git] / source / blender / blenkernel / intern / sound.c
1 /**
2  * sound.c (mar-2001 nzc)
3  *
4  * $Id$
5  */
6
7 #include <string.h>
8 #include <stdlib.h>
9
10 #include "MEM_guardedalloc.h"
11
12 #include "BLI_blenlib.h"
13
14 #include "DNA_anim_types.h"
15 #include "DNA_scene_types.h"
16 #include "DNA_sequence_types.h"
17 #include "DNA_packedFile_types.h"
18 #include "DNA_screen_types.h"
19 #include "DNA_sound_types.h"
20
21 #include "AUD_C-API.h"
22
23 #include "BKE_utildefines.h"
24 #include "BKE_global.h"
25 #include "BKE_main.h"
26 #include "BKE_sound.h"
27 #include "BKE_context.h"
28 #include "BKE_library.h"
29 #include "BKE_packedFile.h"
30 #include "BKE_fcurve.h"
31 #include "BKE_animsys.h"
32
33
34 static int force_device = -1;
35
36 #ifdef WITH_JACK
37 static void sound_sync_callback(void* data, int mode, float time)
38 {
39         struct Main* bmain = (struct Main*)data;
40         struct Scene* scene;
41
42         scene = bmain->scene.first;
43         while(scene)
44         {
45                 if(scene->audio.flag & AUDIO_SYNC)
46                 {
47                         if(mode)
48                                 sound_play_scene(scene);
49                         else
50                                 sound_stop_scene(scene);
51                         AUD_seek(scene->sound_scene_handle, time);
52                 }
53                 scene = scene->id.next;
54         }
55 }
56 #endif
57
58 int sound_define_from_str(char *str)
59 {
60         if (BLI_strcaseeq(str, "NULL"))
61                 return AUD_NULL_DEVICE;
62         if (BLI_strcaseeq(str, "SDL"))
63                 return AUD_SDL_DEVICE;
64         if (BLI_strcaseeq(str, "OPENAL"))
65                 return AUD_OPENAL_DEVICE;
66         if (BLI_strcaseeq(str, "JACK"))
67                 return AUD_JACK_DEVICE;
68
69         return -1;
70 }
71
72 void sound_force_device(int device)
73 {
74         force_device = device;
75 }
76
77 void sound_init_once()
78 {
79         AUD_initOnce();
80 }
81
82 void sound_init(struct Main *bmain)
83 {
84         AUD_DeviceSpecs specs;
85         int device, buffersize;
86
87         device = U.audiodevice;
88         buffersize = U.mixbufsize;
89         specs.channels = U.audiochannels;
90         specs.format = U.audioformat;
91         specs.rate = U.audiorate;
92
93         if(force_device >= 0)
94                 device = force_device;
95
96         if(buffersize < 128)
97                 buffersize = AUD_DEFAULT_BUFFER_SIZE;
98
99         if(specs.rate < AUD_RATE_8000)
100                 specs.rate = AUD_RATE_44100;
101
102         if(specs.format <= AUD_FORMAT_INVALID)
103                 specs.format = AUD_FORMAT_S16;
104
105         if(specs.channels <= AUD_CHANNELS_INVALID)
106                 specs.channels = AUD_CHANNELS_STEREO;
107
108         if(!AUD_init(device, specs, buffersize))
109                 AUD_init(AUD_NULL_DEVICE, specs, buffersize);
110                 
111 #ifdef WITH_JACK
112         AUD_setSyncCallback(sound_sync_callback, bmain);
113 #endif
114 }
115
116 void sound_exit()
117 {
118         AUD_exit();
119 }
120
121 struct bSound* sound_new_file(struct Main *bmain, char* filename)
122 {
123         bSound* sound = NULL;
124
125         char str[FILE_MAX];
126         char *path;
127
128         int len;
129
130         strcpy(str, filename);
131
132         path = /*bmain ? bmain->name :*/ G.sce;
133
134         BLI_path_abs(str, path);
135
136         len = strlen(filename);
137         while(len > 0 && filename[len-1] != '/' && filename[len-1] != '\\')
138                 len--;
139
140         sound = alloc_libblock(&bmain->sound, ID_SO, filename+len);
141         BLI_strncpy(sound->name, filename, FILE_MAX);
142 // XXX unused currently sound->type = SOUND_TYPE_FILE;
143
144         sound_load(bmain, sound);
145
146         if(!sound->playback_handle)
147         {
148                 free_libblock(&bmain->sound, sound);
149                 sound = NULL;
150         }
151
152         return sound;
153 }
154
155 // XXX unused currently
156 #if 0
157 struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source)
158 {
159         bSound* sound = NULL;
160
161         char name[25];
162         strcpy(name, "buf_");
163         strcpy(name + 4, source->id.name);
164
165         sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
166
167         sound->child_sound = source;
168         sound->type = SOUND_TYPE_BUFFER;
169
170         sound_load(CTX_data_main(C), sound);
171
172         if(!sound->playback_handle)
173         {
174                 free_libblock(&CTX_data_main(C)->sound, sound);
175                 sound = NULL;
176         }
177
178         return sound;
179 }
180
181 struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, float start, float end)
182 {
183         bSound* sound = NULL;
184
185         char name[25];
186         strcpy(name, "lim_");
187         strcpy(name + 4, source->id.name);
188
189         sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
190
191         sound->child_sound = source;
192         sound->start = start;
193         sound->end = end;
194         sound->type = SOUND_TYPE_LIMITER;
195
196         sound_load(CTX_data_main(C), sound);
197
198         if(!sound->playback_handle)
199         {
200                 free_libblock(&CTX_data_main(C)->sound, sound);
201                 sound = NULL;
202         }
203
204         return sound;
205 }
206 #endif
207
208 void sound_delete(struct bContext *C, struct bSound* sound)
209 {
210         if(sound)
211         {
212                 sound_free(sound);
213
214                 free_libblock(&CTX_data_main(C)->sound, sound);
215         }
216 }
217
218 void sound_cache(struct bSound* sound, int ignore)
219 {
220         if(sound->cache && !ignore)
221                 AUD_unload(sound->cache);
222
223         sound->cache = AUD_bufferSound(sound->handle);
224         sound->playback_handle = sound->cache;
225 }
226
227 void sound_delete_cache(struct bSound* sound)
228 {
229         if(sound->cache)
230         {
231                 AUD_unload(sound->cache);
232                 sound->cache = NULL;
233                 sound->playback_handle = sound->handle;
234         }
235 }
236
237 void sound_load(struct Main *bmain, struct bSound* sound)
238 {
239         if(sound)
240         {
241                 if(sound->handle)
242                 {
243                         AUD_unload(sound->handle);
244                         sound->handle = NULL;
245                         sound->playback_handle = NULL;
246                 }
247
248 // XXX unused currently
249 #if 0
250                 switch(sound->type)
251                 {
252                 case SOUND_TYPE_FILE:
253 #endif
254                 {
255                         char fullpath[FILE_MAX];
256                         char *path;
257
258                         /* load sound */
259                         PackedFile* pf = sound->packedfile;
260
261                         /* dont modify soundact->sound->name, only change a copy */
262                         BLI_strncpy(fullpath, sound->name, sizeof(fullpath));
263
264                         if(sound->id.lib)
265                                 path = sound->id.lib->filepath;
266                         else
267                                 path = /*bmain ? bmain->name :*/ G.sce;
268
269                         BLI_path_abs(fullpath, path);
270
271                         /* but we need a packed file then */
272                         if (pf)
273                                 sound->handle = AUD_loadBuffer((unsigned char*) pf->data, pf->size);
274                         /* or else load it from disk */
275                         else
276                                 sound->handle = AUD_load(fullpath);
277                 } // XXX
278 // XXX unused currently
279 #if 0
280                         break;
281                 }
282                 case SOUND_TYPE_BUFFER:
283                         if(sound->child_sound && sound->child_sound->handle)
284                                 sound->handle = AUD_bufferSound(sound->child_sound->handle);
285                         break;
286                 case SOUND_TYPE_LIMITER:
287                         if(sound->child_sound && sound->child_sound->handle)
288                                 sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end);
289                         break;
290                 }
291 #endif
292                 if(sound->cache)
293                         sound->playback_handle = sound->cache;
294                 else
295                         sound->playback_handle = sound->handle;
296         }
297 }
298
299 void sound_free(struct bSound* sound)
300 {
301         if (sound->packedfile)
302         {
303                 freePackedFile(sound->packedfile);
304                 sound->packedfile = NULL;
305         }
306
307         if(sound->handle)
308         {
309                 AUD_unload(sound->handle);
310                 sound->handle = NULL;
311                 sound->playback_handle = NULL;
312         }
313 }
314
315 static float sound_get_volume(Scene* scene, Sequence* sequence, float time)
316 {
317         AnimData *adt= BKE_animdata_from_id(&scene->id);
318         FCurve *fcu = NULL;
319         char buf[64];
320         
321         /* NOTE: this manually constructed path needs to be used here to avoid problems with RNA crashes */
322         sprintf(buf, "sequence_editor.sequences_all[\"%s\"].volume", sequence->name+2);
323         if (adt && adt->action && adt->action->curves.first)
324                 fcu= list_find_fcurve(&adt->action->curves, buf, 0);
325         
326         if(fcu)
327                 return evaluate_fcurve(fcu, time * FPS);
328         else
329                 return sequence->volume;
330 }
331
332 AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
333 {
334         AUD_Device* mixdown = AUD_openReadDevice(specs);
335
336         AUD_setDeviceVolume(mixdown, volume);
337
338         AUD_playDevice(mixdown, scene->sound_scene, start / FPS);
339
340         return mixdown;
341 }
342
343 void sound_create_scene(struct Scene *scene)
344 {
345         scene->sound_scene = AUD_createSequencer(scene, (AUD_volumeFunction)&sound_get_volume);
346 }
347
348 void sound_destroy_scene(struct Scene *scene)
349 {
350         if(scene->sound_scene_handle)
351                 AUD_stop(scene->sound_scene_handle);
352         if(scene->sound_scene)
353                 AUD_destroySequencer(scene->sound_scene);
354 }
355
356 void* sound_scene_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip)
357 {
358         if(scene != sequence->scene)
359                 return AUD_addSequencer(scene->sound_scene, &(sequence->scene->sound_scene), startframe / FPS, endframe / FPS, frameskip / FPS, sequence);
360         return NULL;
361 }
362
363 void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip)
364 {
365         return AUD_addSequencer(scene->sound_scene, &(sequence->sound->playback_handle), startframe / FPS, endframe / FPS, frameskip / FPS, sequence);
366 }
367
368 void sound_remove_scene_sound(struct Scene *scene, void* handle)
369 {
370         AUD_removeSequencer(scene->sound_scene, handle);
371 }
372
373 void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute)
374 {
375         AUD_muteSequencer(scene->sound_scene, handle, mute);
376 }
377
378 void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, int endframe, int frameskip)
379 {
380         AUD_moveSequencer(scene->sound_scene, handle, startframe / FPS, endframe / FPS, frameskip / FPS);
381 }
382
383 void sound_start_play_scene(struct Scene *scene)
384 {
385         scene->sound_scene_handle = AUD_play(scene->sound_scene, 1);
386         AUD_setLoop(scene->sound_scene_handle, -1);
387 }
388
389 void sound_play_scene(struct Scene *scene)
390 {
391         AUD_Status status;
392         AUD_lock();
393
394         status = AUD_getStatus(scene->sound_scene_handle);
395
396         if(status == AUD_STATUS_INVALID)
397                 sound_start_play_scene(scene);
398
399         if(status != AUD_STATUS_PLAYING)
400         {
401                 AUD_seek(scene->sound_scene_handle, CFRA / FPS);
402                 AUD_resume(scene->sound_scene_handle);
403         }
404
405         if(scene->audio.flag & AUDIO_SYNC)
406                 AUD_startPlayback();
407
408         AUD_unlock();
409 }
410
411 void sound_stop_scene(struct Scene *scene)
412 {
413         AUD_pause(scene->sound_scene_handle);
414
415         if(scene->audio.flag & AUDIO_SYNC)
416                 AUD_stopPlayback();
417 }
418
419 void sound_seek_scene(struct bContext *C)
420 {
421         struct Scene *scene = CTX_data_scene(C);
422         AUD_Status status;
423
424         AUD_lock();
425
426         status = AUD_getStatus(scene->sound_scene_handle);
427
428         if(status == AUD_STATUS_INVALID)
429         {
430                 sound_start_play_scene(scene);
431                 AUD_pause(scene->sound_scene_handle);
432         }
433
434         if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
435         {
436                 // AUD_XXX TODO: fix scrubbing, it currently doesn't stop playing
437                 if(scene->audio.flag & AUDIO_SYNC)
438                         AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS);
439                 else
440                         AUD_seek(scene->sound_scene_handle, CFRA / FPS);
441                 AUD_resume(scene->sound_scene_handle);
442                 if(AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID)
443                         AUD_seek(scene->sound_scrub_handle, 0);
444                 else
445                         scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS);
446         }
447         else
448         {
449                 if(scene->audio.flag & AUDIO_SYNC)
450                         AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS);
451                 else
452                 {
453                         if(status == AUD_STATUS_PLAYING)
454                                 AUD_seek(scene->sound_scene_handle, CFRA / FPS);
455                 }
456         }
457
458         AUD_unlock();
459 }
460
461 float sound_sync_scene(struct Scene *scene)
462 {
463         if(scene->audio.flag & AUDIO_SYNC)
464                 return AUD_getSequencerPosition(scene->sound_scene_handle);
465         else
466                 return AUD_getPosition(scene->sound_scene_handle);
467 }
468
469 int sound_scene_playing(struct Scene *scene)
470 {
471         if(scene->audio.flag & AUDIO_SYNC)
472                 return AUD_doesPlayback();
473         else
474                 return -1;
475 }
476
477 int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length, float start, float end)
478 {
479         AUD_Sound* limiter = AUD_limitSound(sound->cache, start, end);
480         return AUD_readSound(limiter, buffer, length);
481         AUD_unload(limiter);
482 }