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