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