for button popups, dont close unless you click or press escape, this would often...
[blender.git] / source / blender / src / editsound.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include <string.h>
37 #include <fcntl.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #ifndef WIN32 
44 #define __USE_XOPEN /* Needed for swab on linux */
45 #include <unistd.h>
46 #undef __USE_XOPEN
47 #else
48
49 #include <io.h>
50 #endif
51 #include "MEM_guardedalloc.h"
52
53 #include "BLI_blenlib.h"
54 #include "BLI_arithb.h"
55
56 #include "DNA_object_types.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_space_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_sound_types.h"
61 #include "DNA_packedFile_types.h"
62 #include "DNA_userdef_types.h"
63
64 #include "BKE_utildefines.h"
65 #include "BKE_global.h"
66 #include "BKE_main.h"
67 #include "BKE_sound.h"
68 #include "BKE_library.h"
69 #include "BKE_packedFile.h"
70
71 #include "BIF_space.h"
72 #include "BIF_screen.h"
73 #include "BIF_interface.h"
74 #include "BIF_editsound.h"
75 #include "BIF_mywindow.h"
76 #include "BIF_toolbox.h"
77
78 #include "BSE_drawipo.h"
79 #include "BSE_headerbuttons.h"
80 #include "BSE_time.h"
81
82 #include "BDR_editobject.h"
83
84 #include "blendef.h"
85
86 #include "mydevice.h"
87
88 #include "SND_C-api.h"
89 #include "SND_DependKludge.h"
90
91 #include "SYS_System.h"
92
93 #include "PIL_time.h"
94
95
96 /* this might move to the external header */
97 void* sound_get_libraryinterface(void);
98
99 static SND_SceneHandle ghSoundScene=NULL;
100 static SND_AudioDeviceInterfaceHandle ghAudioDeviceInterface=NULL;
101
102 /* que? why only here? because of the type define? */
103 bSound *sound_find_sound(char *id_name);
104 void sound_read_wav_data(bSound * sound, PackedFile * pf);
105 void sound_stop_sound(void *object, bSound *sound);
106 void winqreadsoundspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt);
107 /*  void sound_stop_all_sounds(void); already in BIF_editsound.h */
108
109
110
111 /* Right. Now for some implementation: */
112 void winqreadsoundspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
113 {
114         SpaceSound *ssound= spacedata;
115         unsigned short event= evt->event;
116         short val= evt->val;
117         float dx, dy;
118         int doredraw= 0, cfra, first = 0;
119         short mval[2], nr;
120         short mousebut = L_MOUSE;
121         
122         if(curarea->win==0) return;
123
124         if(val) {
125                 
126                 if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
127
128                 /* swap mouse buttons based on user preference */
129                 if (U.flag & USER_LMOUSESELECT) {
130                         if (event == LEFTMOUSE) {
131                                 event = RIGHTMOUSE;
132                                 mousebut = L_MOUSE;
133                         } else if (event == RIGHTMOUSE) {
134                                 event = LEFTMOUSE;
135                                 mousebut = R_MOUSE;
136                         }
137                 }
138
139                 switch(event) {
140                 case LEFTMOUSE:
141                         ssound->flag |= SND_CFRA_NUM;
142                         do {
143                                 getmouseco_areawin(mval);
144                                 areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
145                                 
146                                 cfra = (int)dx;
147                                 if(cfra< 1) cfra= 1;
148                                 
149                                 if( cfra!=CFRA || first )
150                                 {
151                                         first= 0;
152                                         CFRA= cfra;
153                                         update_for_newframe();
154                                         force_draw_plus(SPACE_VIEW3D, 1);
155                                 }
156                                 else PIL_sleep_ms(30);
157                         
158                         } while(get_mbut() & mousebut);
159                         ssound->flag &= ~SND_CFRA_NUM;
160                         
161                         doredraw= 1;
162
163                         break;
164                 case MIDDLEMOUSE:
165                 case WHEELUPMOUSE:
166                 case WHEELDOWNMOUSE:
167                         view2dmove(event);      /* in drawipo.c */
168                         break;
169                 case RIGHTMOUSE:
170                         {
171                                 TimeMarker *marker;
172                                 
173                                 getmouseco_areawin(mval);
174                                 areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
175
176                                 marker = find_nearest_marker(0);
177                                 if (marker) {
178                                         if ((G.qual & LR_SHIFTKEY)==0)
179                                                 deselect_markers(0, 0);
180                                                 
181                                         if (marker->flag & SELECT)
182                                                 marker->flag &= ~SELECT;
183                                         else
184                                                 marker->flag |= SELECT;
185                                 }
186                                 
187                                 force_draw(0);
188                                 std_rmouse_transform(transform_markers);
189                         }
190                         break;
191                         
192                 case PADPLUSKEY:
193                         dx= (float)(0.1154*(G.v2d->cur.xmax-G.v2d->cur.xmin));
194                         G.v2d->cur.xmin+= dx;
195                         G.v2d->cur.xmax-= dx;
196                         test_view2d(G.v2d, curarea->winx, curarea->winy);
197                         view2d_do_locks(curarea, V2D_LOCK_COPY);
198                         doredraw= 1;
199                         break;
200                 case PADMINUS:
201                         dx= (float)(0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin));
202                         G.v2d->cur.xmin-= dx;
203                         G.v2d->cur.xmax+= dx;
204                         test_view2d(G.v2d, curarea->winx, curarea->winy);
205                         view2d_do_locks(curarea, V2D_LOCK_COPY);
206                         doredraw= 1;
207                         break;
208                 case HOMEKEY:
209                         do_sound_buttons(B_SOUNDHOME);
210                         break;
211                         
212                 case PAGEUPKEY: /* cfra to next marker */
213                         nextprev_marker(1);
214                         break;
215                 case PAGEDOWNKEY: /* cfra to prev marker */
216                         nextprev_marker(-1);
217                         break;
218                 
219                 case AKEY: /* select/deselect all  */
220                         deselect_markers(1, 0);
221                         
222                         allqueue(REDRAWMARKER, 0);
223                         break;
224                         
225                 case BKEY: /* borderselect markers */
226                         borderselect_markers();
227                         break;
228                 
229                 case DKEY: /* duplicate selected marker(s) */
230                         if (G.qual & LR_SHIFTKEY) {
231                                 duplicate_marker();
232                                 
233                                 allqueue(REDRAWMARKER, 0);
234                         }
235                         break;
236                         
237                 case GKEY:
238                         transform_markers('g', 0);
239                         break;
240                         
241                 case MKEY: /* add marker or rename first selected */
242                         if (G.qual & LR_CTRLKEY)
243                                 rename_marker();
244                         else
245                                 add_marker(CFRA);
246                         
247                         allqueue(REDRAWMARKER, 0);
248                         break;          
249                 
250                 case TKEY: /* toggle time display */
251                         nr= pupmenu("Time value%t|Frames %x1|Seconds%x2");
252                         if (nr>0) {
253                                 if(nr==1) ssound->flag |= SND_DRAWFRAMES;
254                                 else ssound->flag &= ~SND_DRAWFRAMES;
255                                 doredraw= 1;
256                         }
257
258                         break;
259                         
260                 case DELKEY: /* delete selected markers */
261                 case XKEY:
262                         if (okee("Erase selected")) {
263                                 remove_marker();
264                                 allqueue(REDRAWMARKER, 0);
265                         }
266                         break;
267                 }
268         }
269
270         if(doredraw)
271                 scrarea_queue_winredraw(curarea);
272 }
273
274
275
276 void sound_initialize_sounds(void)
277 {
278         bSound *sound;
279
280         if(ghSoundScene) {
281
282                 /* clear the soundscene */
283                 SND_RemoveAllSounds(ghSoundScene);
284                 SND_RemoveAllSamples(ghSoundScene);
285         }
286         
287         /* initialize sample blocks (doesnt call audio system, needs to be done once after load */
288         sound = G.main->sound.first;
289         while (sound) {
290                 sound_sample_is_null(sound);
291                 sound = (bSound *) sound->id.next;
292         }
293 }
294
295
296
297 bSound *sound_make_copy(bSound *originalsound)
298 {
299         bSound *sound = NULL;
300         char name[160];
301         int len;
302         
303         if(ghSoundScene==NULL) sound_init_audio();
304         
305         /* only copy sounds that are sounds */
306         if (originalsound)
307         {
308                 /* do some name magic */
309                 strcpy(name, originalsound->name);
310                 len = strlen(name);
311                 while ((len > 0) && (name[len - 1] != '/') && (name[len - 1] != '\\'))
312                         len--;
313                 
314                 /* allocate the needed memory */
315                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
316                 
317                 /* create a soundobject */
318                 sound->snd_sound = SND_CreateSound();
319
320                 /* set the samplename */
321                 strcpy(sound->name, name);
322                 SND_SetSampleName(sound->snd_sound, sound->name);
323
324                 /* add the new object to the soundscene */
325                 SND_AddSound(ghSoundScene, sound->snd_sound);
326                 
327                 /* and copy the data from the original */
328                 sound->attenuation = originalsound->attenuation;
329                 sound->distance = originalsound->distance;
330                 sound->max_gain = originalsound->max_gain;
331                 sound->min_gain = originalsound->min_gain;
332                 sound->newpackedfile = originalsound->newpackedfile;
333                 sound->panning = originalsound->panning;
334                 sound->pitch = originalsound->pitch;
335                 sound->sample = originalsound->sample;
336                 sound->volume = originalsound->volume;
337                 
338                 if (originalsound->flags & SOUND_FLAGS_3D)
339                         sound->flags |= SOUND_FLAGS_3D;
340                 else
341                         sound->flags &= ~SOUND_FLAGS_3D;
342         }
343         
344         return sound;
345 }
346
347
348
349 void sound_initialize_sample(bSound *sound)
350 {
351         if(ghSoundScene==NULL) sound_init_audio();
352
353         if (sound && sound->sample == NULL)
354                 sound_sample_is_null(sound);
355 }
356
357
358 void sound_read_wav_data(bSound *sound, PackedFile *pf)
359 {
360         int i, temp;
361         short shortbuf, *temps;
362         int longbuf;
363         char buffer[25];
364         char *data = NULL;
365         char *tempc;
366         bSample *sample = NULL;
367         int channels, rate, bits, len;
368         
369         /* prepare for the worst... */
370         sound->sample->type = SAMPLE_INVALID;
371
372         rewindPackedFile(pf);
373
374         /* check to see if it is a file in "RIFF WAVE fmt" format */
375         if (readPackedFile(pf, buffer, 16) != 16) {
376                 if (G.f & G_DEBUG) printf("File too short\n");
377                 return;
378         }
379
380         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8))) {
381                 readPackedFile(pf, &i, 4);// start of data
382                 if(G.order==B_ENDIAN)
383                         SWITCH_INT(i);
384
385                 /* read the sampleformat */
386                 readPackedFile(pf, &shortbuf, 2);
387                 if(G.order==B_ENDIAN) {
388                         SWITCH_SHORT(shortbuf);
389                 }
390
391                 /* read the number of channels */
392                 readPackedFile(pf, &shortbuf, 2);
393
394                 if(G.order==B_ENDIAN) {
395                         SWITCH_SHORT(shortbuf);
396                 }
397
398                 /* check the number of channels */
399                 if(shortbuf != 1 && shortbuf != 2) {
400                         if (G.f & G_DEBUG) printf("Unsupported number of channels\n");
401                         return;
402                 }
403                 channels = shortbuf;
404                 
405                 /* read the samplerate */
406                 readPackedFile(pf, &longbuf, 4);
407
408
409                 if(G.order==B_ENDIAN)
410                         SWITCH_INT(longbuf);
411                 rate = longbuf;
412                 
413                 /* read the bitrate */
414                 // Ton's way
415                 readPackedFile(pf, &temp, 4);
416
417                 if(G.order==B_ENDIAN)
418                         SWITCH_INT(temp);
419
420                 if(channels && rate)
421                         bits= 8*temp/(rate * channels);
422                 
423                 // Frank's way
424
425                 readPackedFile(pf, &shortbuf, 2);
426                 readPackedFile(pf, &shortbuf, 2);
427                 if(G.order==B_ENDIAN) {
428                         SWITCH_SHORT(shortbuf);
429                 }
430                 bits = shortbuf;
431                 
432                 seekPackedFile(pf, i-16, SEEK_CUR);
433                 readPackedFile(pf, buffer, 4);
434                 /* check if we have a 'data' chunk */
435                 while(memcmp(buffer, "data", 4)!=0) {
436                         if (readPackedFile(pf, &i, 4) != 4)
437                                 break;
438                         
439                         if(G.order==B_ENDIAN)
440                                 SWITCH_INT(i);
441
442                         seekPackedFile(pf, i, SEEK_CUR);
443                         if (readPackedFile(pf, buffer, 4) != 4)
444                                 break;
445                 }
446                 
447                 /* guess not */
448                 if (memcmp(buffer, "data", 4) !=0) {
449                         if (G.f & G_DEBUG) printf("No data found\n");
450                 }
451                 /* or maybe we do! */
452                 else {
453                         readPackedFile(pf, &longbuf, 4); 
454                         if(G.order==B_ENDIAN) SWITCH_INT(longbuf);
455                         
456                         /* handle 8 and 16 bit samples differently */
457                         /* intrr: removed, longbuf is length in bytes, not samples */
458                         if (bits == 16)
459                                 data = (char *)MEM_mallocN(longbuf, "sample data");
460                         else 
461                                 data = (char *)MEM_mallocN(longbuf*2, "sample data");
462
463                         len = longbuf /*/ 4.0*/; /* for some strange reason the sample length is off by a factor of 4... */
464                         /* intrr's comment: Funny eh, how one 16-bit stereo sample is 4 bytes? :-) */
465                         
466                         if(data) {
467                                 readPackedFile(pf, data, len);
468                                 /* data is only used to draw! */
469                                 if (bits == 8) {
470                                         temps = (short *) data;
471                                         tempc = (char *) data;
472                                         for (i = len - 1; i >= 0; i--)
473                                                 temps[i] = tempc[i] << 8;
474                                 }
475                                 else {
476                                         if(G.order==B_ENDIAN) {
477                                                 swab(data, data, len);
478                                         }
479                                 }
480                                 /* fill the sound with the found data */
481                                 sample = sound->sample;
482                                 sample->channels = channels;
483                                 sample->rate = rate;
484                                 sample->bits = bits;
485                                 sample->len = len;
486                                 sample->data = data;
487                                 sample->type = SAMPLE_WAV;
488                         }
489                 }
490         }
491         else {
492                 sound->sample->type = SAMPLE_INVALID;
493                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
494         }
495 }
496
497
498
499 /* ugly, but it works (for now) */
500 static int sound_get_filetype_from_header(bSound *sound, PackedFile *pf)
501 {
502         int filetype = SAMPLE_INVALID;
503         int i;
504         char buffer[25];
505         short shortbuf;
506         
507         rewindPackedFile(pf);
508         
509         if (readPackedFile(pf, buffer, 16) != 16) {
510                 if (G.f & G_DEBUG) printf("File too short\n");
511                 return filetype;
512         }
513         
514         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8))) {
515                 readPackedFile(pf, &i, 4);
516                 if(G.order==B_ENDIAN)
517                         SWITCH_INT(i);
518                 
519                 /* read the sampleformat */
520                 readPackedFile(pf, &shortbuf, 2);
521                 if(G.order==B_ENDIAN) {
522                         char s_i, *p_i;
523                         p_i= (char *)&(shortbuf);
524                         s_i= p_i[0];
525                         p_i[0]= p_i[1];
526                         p_i[1]= s_i;
527                 }
528                 
529                 if (shortbuf == SND_WAVE_FORMAT_PCM) {
530                         filetype = SAMPLE_WAV;
531                 }
532                 else
533                         /* only fmod supports compressed wav */
534 #ifdef USE_FMOD
535                 {
536                         /* and only valid publishers may use compressed wav */
537                         switch (shortbuf)
538                         {
539                         case SND_WAVE_FORMAT_ADPCM:
540                         case SND_WAVE_FORMAT_ALAW:
541                         case SND_WAVE_FORMAT_MULAW:
542                         case SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
543                         case SND_WAVE_FORMAT_CONTROL_RES_VQLPC:
544                         case SND_WAVE_FORMAT_GSM_610:
545                         case SND_WAVE_FORMAT_MPEG3:
546                                 filetype = SAMPLE_WAV;
547                                 break;
548                         default:
549 #endif
550                                 {
551                                         filetype = SAMPLE_INVALID;
552                                         if (G.f & G_DEBUG) printf("Unsupported wav compression\n");
553                                 }
554                         }
555 #ifdef USE_FMOD
556                 }
557         }
558         else if (!memcmp(buffer, "OggS", 4)) {
559                 filetype = SAMPLE_OGG_VORBIS;
560         }
561         else if ((!memcmp(buffer, "ID3", 3)) || (!memcmp(buffer, "", 2))) {
562                 filetype = SAMPLE_MP3;
563         }
564 #endif
565         else {
566                 filetype = SAMPLE_INVALID;
567                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
568         }
569         
570         return filetype;
571 }
572
573
574
575 static int check_filetype(bSound *sound, PackedFile *pf)
576 {
577 //      char* pdest;
578         sound->sample->type = SAMPLE_INVALID;
579 /*      
580         // parse the name for the extension to see what kind of sample it is
581         pdest = strrchr(sound->sample->name, '.');
582
583         // a simple check to see what kind of sample we're dealing with
584         if (stricmp(pdest, ".wav") == 0)
585                 sound->sample->type = SAMPLE_WAV;
586
587 #ifdef USE_FMOD
588         if (stricmp(pdest, ".mp2") == 0)
589                 sound->sample->type = SAMPLE_MP2;
590         if (stricmp(pdest, ".mp3") == 0)
591                 sound->sample->type = SAMPLE_MP3;
592         if (stricmp(pdest, ".ogg") == 0)
593                 sound->sample->type = SAMPLE_OGG_VORBIS;
594         if (stricmp(pdest, ".raw") == 0)
595                 sound->sample->type = SAMPLE_RAW;
596         if (stricmp(pdest, ".wma") == 0)
597                 sound->sample->type = SAMPLE_WMA;
598         if (stricmp(pdest, ".asf") == 0)
599                 sound->sample->type = SAMPLE_ASF;
600 #endif
601 */
602         sound->sample->type = sound_get_filetype_from_header(sound, pf);
603
604         /* get some info from the sample */
605         switch (sound->sample->type) {
606         case SAMPLE_WAV:
607                 {
608                         sound_read_wav_data(sound, pf);
609                         break;
610                 }
611         case SAMPLE_OGG_VORBIS:
612         case SAMPLE_MP3:
613         case SAMPLE_MP2:
614         case SAMPLE_RAW:
615         case SAMPLE_WMA:
616         case SAMPLE_ASF:
617                 break;
618         default:
619                 {
620                         if (G.f & G_DEBUG) printf("No valid sample: %s\n", sound->name);
621                         break;
622                 }
623         }
624         
625         return sound->sample->type;
626 }
627
628
629
630 int sound_load_sample(bSound *sound)
631 {
632         int result = FALSE;
633         PackedFile *pf;
634         int freePF = FALSE;
635         int buffer = -1;
636
637         if(ghSoundScene==NULL) sound_init_audio();
638
639         /* check the sample (valid?) */
640         if (sound->sample->type == SAMPLE_UNKNOWN || sound->snd_sound == NULL) {
641                 /* find... */
642                 pf = sound_find_packedfile(sound);
643
644                 /* ...or create a (temp)packedfile */
645                 if (pf == NULL) {
646                         pf = newPackedFile(sound->name);
647                         
648                         /* if autopack is off, free the pf afterwards */
649                         if ((G.fileflags & G_AUTOPACK) == 0)
650                                 freePF = TRUE;
651                 }
652                 
653                 /* if we have a valid pf... */
654                 if (pf) {
655                         /* check the content of the pf */
656                         check_filetype(sound, pf);
657
658                         /* check if the sampletype is supported */
659                         if (sound->sample->type != SAMPLE_INVALID && sound->sample->type != SAMPLE_UNKNOWN) {
660                                 /* register the sample at the audiodevice */
661                                 buffer = SND_AddSample(ghSoundScene, sound->sample->name, pf->data, pf->size);
662
663                                 /* create a soundobject */
664                                 sound->snd_sound = SND_CreateSound();
665                                 SND_SetSampleName(sound->snd_sound, sound->sample->name);
666                                         
667                                 /* add the soundobject to the soundscene  */
668                                 if (SND_CheckBuffer(ghSoundScene, sound->snd_sound))
669                                         SND_AddSound(ghSoundScene, sound->snd_sound);
670                                 else
671                                         if (G.f & G_DEBUG) printf("error: sample didn't load properly\n");
672                                 
673                                 /* if it was places in buffer[0] or higher, it succeeded */
674                                 if (buffer >= 0)
675                                         result = TRUE;
676                         }
677                         /* if not, free the pf */
678                         else {
679                                 freePF = TRUE;
680                         }
681                         
682                         /* if you want it freed, make it so */
683                         if (freePF) {
684                                 freePackedFile(pf);
685                                 pf = NULL;
686                         } 
687                         /* or else connect the pf to the sound and sample */
688 //                      else {
689                                 sound->newpackedfile = pf;
690                                 sound->sample->packedfile = pf;
691 //                      }
692                 }
693                 else  {
694                         if (G.f & G_DEBUG) printf("%s: File not found!\n", sound->name);
695                         sound->sample->type = SAMPLE_INVALID;
696                 }
697         }
698         /* if the sample ain't invalid, we're ready to go! */
699         else if (sound->sample->type != SAMPLE_INVALID) {
700                 result = TRUE;
701         }
702
703         return result;
704 }
705
706
707
708 bSound *sound_new_sound(char *name)
709 {
710         bSound *sound = NULL;
711         int len, file;
712         char str[FILE_MAXDIR+FILE_MAXFILE];
713
714         if(ghSoundScene==NULL) sound_init_audio();
715
716         if (!G.scene->audio.mixrate) G.scene->audio.mixrate = 44100;
717         /* convert the name to absolute path */
718         strcpy(str, name);
719         BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
720
721         /* check if the sample on disk can be opened */
722         file = open(str, O_BINARY|O_RDONLY);
723         
724         if (file != -1) {
725                 close(file);
726
727
728                 /* do some name magic */
729                 len = strlen(name);
730                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
731                         len--;
732                 
733                 /* allocate some memory for the sound */
734                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
735                 strcpy(sound->name, name);
736                 
737                 /* intialize and check the sample */
738                 sound_initialize_sample(sound);
739
740                 /* load the sample & check if this blender supports the sound format */
741 //              sound_load_sample(sound);
742
743                 if (sound->sample->type == SAMPLE_INVALID) {
744                         free_libblock(&G.main->sound, sound);
745                         sound = NULL;
746                 } 
747                 else
748                 {
749                         sound->volume = 1.0;
750                         sound->attenuation = 1.0;
751                         sound->distance = 1.0;
752                         sound->min_gain = 0.0;
753                         sound->max_gain = 1.0;
754                 }
755         }
756         
757         return (sound);
758 }
759
760
761
762 int sound_set_sample(bSound *sound, bSample *sample)
763 {
764         int result = TRUE;
765         
766         if(ghSoundScene==NULL) sound_init_audio();
767         
768         /* delete the soundobject */
769         if (sound->snd_sound) {
770                 SND_RemoveSound(ghSoundScene, sound->snd_sound);
771                 sound->snd_sound = NULL;
772         }
773
774         /* connect the sample to the sound */
775         sound->sample = sample;
776         sound->newpackedfile = NULL;
777         
778         if (sound->sample) {
779
780                 /* and set the right pf */
781                 sound->newpackedfile = sample->packedfile;
782
783                 /* if the sampletype is unknown initialize it */
784                 if (sound->sample->type == SAMPLE_UNKNOWN) {
785                         sound_initialize_sample(sound);
786                         
787                         /* load the sample & check if this blender supports the sound format */
788                         if (!sound_load_sample(sound)) {
789                                 result = FALSE;
790                         }
791                 }
792         }
793
794         return result;
795 }
796
797
798
799 bSample *sound_new_sample(bSound *sound)
800 {
801         bSample *sample = NULL;
802         int len;
803         char *name;
804         
805         if (sound != NULL) {
806                 name = sound->name;     
807                 len = strlen(name);
808                 /* do some name magic */
809                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
810                         len--;
811                 
812                 /* allocate the memory for the sample */
813                 sample = MEM_callocN(sizeof(bSample), "sample");
814                 BLI_strncpy(sample->id.name+2, name+len, 20);
815                 BLI_addtail(samples, sample);   /* samples is ugly global */
816                 
817                 sample->data = &sample->fakedata[0];
818                 sample->type = SAMPLE_UNKNOWN;
819                 
820                 /* some default settings. We get divide by zero if these values are not set     */
821                 sample->channels = 1;
822                 sample->rate = 44100;
823                 sample->bits = 16;
824                 sample->alindex = SAMPLE_INVALID;
825
826                 /* convert sound->name to abolute filename */
827                 strcpy(sample->name, sound->name);
828                 BLI_convertstringcode(sample->name, G.sce, G.scene->r.cfra);
829                 
830                 /* connect the pf to the sample */
831                 if (sound->newpackedfile)
832                         sample->packedfile = sound->newpackedfile;
833                 else
834                         sample->packedfile = sound_find_packedfile(sound);
835         }
836         
837         return(sample);
838 }
839
840
841
842 /* find a sample that might already be loaded */
843 bSample *sound_find_sample(bSound *sound)
844 {
845         bSample *sample;
846         char name[FILE_MAXDIR + FILE_MAXFILE];
847         char samplename[FILE_MAXDIR + FILE_MAXFILE];
848         
849         // convert sound->name to abolute filename
850         strcpy(name, sound->name);
851         BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
852         
853         /* search through the list of loaded samples */
854         sample = samples->first;
855         while (sample) {
856                 strcpy(samplename, sample->name);
857                 BLI_convertstringcode(samplename, G.sce, G.scene->r.cfra);
858                 
859                 if (strcmp(name, samplename) == 0)      {
860                         break;
861                 }
862                 sample = sample->id.next;
863         }
864         
865         return (sample);
866 }
867
868
869
870 int sound_sample_is_null(bSound *sound)
871 {
872         int result = FALSE;
873         bSample *sample;
874         
875         if(ghSoundScene==NULL) sound_init_audio();
876         
877         /* find the right sample or else create one */
878         if (sound->sample == NULL) {
879                 /* find... */
880                 sample = sound_find_sample(sound);
881
882                 /* or a new one? */
883                 if (sample == NULL)
884                         sample = sound_new_sample(sound);
885                 
886                 if (sound_set_sample(sound, sample))
887                         result = TRUE;
888         }
889
890         return result;
891 }
892
893
894
895 void sound_stop_all_sounds(void)
896 {
897 #if GAMEBLENDER == 1
898         if(ghSoundScene) {
899                 SND_StopAllSounds(ghSoundScene);
900                 SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
901         }
902 #endif 
903 }
904
905
906
907 void sound_end_all_sounds(void)
908 {
909 #if GAMEBLENDER == 1
910         if(ghSoundScene) {
911                 sound_stop_all_sounds();
912                 SND_RemoveAllSounds(ghSoundScene);
913         }
914 #endif
915 }
916
917
918
919 void sound_play_sound(bSound *sound)
920 {
921 #if GAMEBLENDER == 1
922         if(ghSoundScene==NULL) sound_init_audio();
923         
924         /* first check if we want sound or not */
925         SND_IsPlaybackWanted(ghSoundScene);
926
927         /* stop all previous sounds */
928         SND_StopAllSounds(ghSoundScene);
929         
930         if (sound != NULL && sound->sample != NULL)
931         {
932                 /* load the sample if needed */
933                 if (sound_load_sample(sound))
934                 {
935                         /* set all kinds of parameters */
936                         SND_SetListenerGain(ghSoundScene, G.listener->gain);
937                         SND_SetDopplerFactor(ghSoundScene, G.listener->dopplerfactor);
938                         SND_SetDopplerVelocity(ghSoundScene, G.listener->dopplervelocity);
939                         
940                         SND_SetGain((SND_ObjectHandle)sound->snd_sound, (sound->volume));
941                         SND_SetPitch((SND_ObjectHandle)sound->snd_sound, (exp((sound->pitch / 12.0) * log(2.0))));
942                         
943                         if (sound->flags & SOUND_FLAGS_LOOP)
944                         {
945                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
946 #ifdef SOUND_UNDER_DEVELOPMENT
947 /*                              SND_SetLoopPoints((SND_ObjectHandle)sound->snd_sound, sound->loopstart, sound->loopend);
948 */
949 #endif
950                                 if (sound->flags & SOUND_FLAGS_BIDIRECTIONAL_LOOP)
951                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_BIDIRECTIONAL);
952                                 else
953                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
954
955                         }
956                         else 
957                         {
958                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_OFF);
959                         }
960                         
961                         if (sound->flags & SOUND_FLAGS_3D)
962                         {
963                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, sound->attenuation);
964                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, sound->distance);
965                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, sound->min_gain);
966                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, sound->max_gain);
967                         }
968                         else
969                         {
970                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, 0);
971                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, 1);
972                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, 1);
973                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, 1);
974                         }
975                         
976                         if (G.f & G_DEBUG) printf("Set pitch to: %f\n", SND_GetPitch((SND_ObjectHandle)sound->snd_sound));
977                         if (G.f & G_DEBUG) printf("Set gain to: %f\n", SND_GetGain((SND_ObjectHandle)sound->snd_sound));
978                         if (G.f & G_DEBUG) printf("Set looping to: %d\n", SND_GetLoopMode((SND_ObjectHandle)sound->snd_sound));
979                         
980                         /* play the sound */
981                         SND_StartSound(ghSoundScene, (SND_ObjectHandle)sound->snd_sound);
982
983                         /* update the device */
984                         SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
985                 }
986         }
987         else 
988         {
989                 if (G.f & G_DEBUG)
990                 {
991                         printf("uninitialized sound !\n");              
992                         if (sound)
993                         {
994                                 printf("sound: %p\n", sound);
995                                 if (sound->sample)
996                                 {
997                                         printf("sample: %p\n", sound->sample);
998                                         if (sound->snd_sound)
999                                                 printf("hSoundObject: %p\n", sound->snd_sound);
1000                                 }
1001                         }
1002                         else
1003                         {
1004                                 printf("sound == NULL\n");
1005                         }
1006                 }
1007         }
1008 #endif 
1009 }
1010
1011
1012
1013 bSound *sound_find_sound(char *id_name)
1014 {
1015         bSound *sound;
1016         
1017         // look for sound with same *id* name
1018         sound = G.main->sound.first;
1019         while (sound)
1020         {
1021                 if (strcmp(sound->id.name + 2, id_name) == 0)
1022                         break;
1023
1024                 sound = sound->id.next;
1025         }
1026         
1027         return sound;
1028 }
1029
1030 void sound_init_audio(void)
1031 {
1032         int noaudio;
1033         SYS_SystemHandle hSystem = NULL;
1034         
1035         if(ghSoundScene==NULL) {
1036                 hSystem = SYS_GetSystem();
1037                 noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0);
1038                 
1039                 if (noaudio)/*(noaudio) intrr: disable game engine audio (openal) */
1040                         SND_SetDeviceType(snd_e_dummydevice);
1041         
1042                 ghAudioDeviceInterface = SND_GetAudioDevice();
1043                 ghSoundScene = SND_CreateScene(ghAudioDeviceInterface);
1044                 // also called after read new file, but doesnt work when no audio initialized
1045                 sound_initialize_sounds();
1046         }
1047 }
1048
1049
1050 int sound_get_mixrate(void)
1051 {
1052         return MIXRATE;
1053 }
1054
1055
1056 void sound_exit_audio(void)
1057 {
1058         if(ghSoundScene) {
1059                 SND_DeleteScene(ghSoundScene);
1060                 SND_ReleaseDevice();
1061                 ghSoundScene = NULL;
1062         }
1063 }