2d70525f971786456abd109b2e70b70d5e5eaf96
[blender-staging.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_all(0);
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                 for(sound=G.main->sound.first; sound; sound=sound->id.next) {
279                         if(sound->snd_sound) {
280                                 SND_RemoveSound(ghSoundScene, sound->snd_sound);
281                                 sound->snd_sound = NULL;
282                         }
283                 }
284
285                 /* clear the soundscene */
286                 SND_RemoveAllSounds(ghSoundScene);
287                 SND_RemoveAllSamples(ghSoundScene);
288         }
289         
290         /* initialize sample blocks (doesnt call audio system, needs to be done once after load */
291         sound = G.main->sound.first;
292         while (sound) {
293                 sound_sample_is_null(sound);
294                 sound = (bSound *) sound->id.next;
295         }
296 }
297
298
299
300 bSound *sound_make_copy(bSound *originalsound)
301 {
302         bSound *sound = NULL;
303         char name[160];
304         int len;
305         
306         if(ghSoundScene==NULL) sound_init_audio();
307         
308         /* only copy sounds that are sounds */
309         if (originalsound)
310         {
311                 /* do some name magic */
312                 strcpy(name, originalsound->name);
313                 len = strlen(name);
314                 while ((len > 0) && (name[len - 1] != '/') && (name[len - 1] != '\\'))
315                         len--;
316                 
317                 /* allocate the needed memory */
318                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
319                 
320                 /* create a soundobject */
321                 sound->snd_sound = SND_CreateSound();
322
323                 /* set the samplename */
324                 strcpy(sound->name, name);
325                 SND_SetSampleName(sound->snd_sound, sound->name);
326
327                 /* add the new object to the soundscene */
328                 SND_AddSound(ghSoundScene, sound->snd_sound);
329                 
330                 /* and copy the data from the original */
331                 sound->attenuation = originalsound->attenuation;
332                 sound->distance = originalsound->distance;
333                 sound->max_gain = originalsound->max_gain;
334                 sound->min_gain = originalsound->min_gain;
335                 sound->newpackedfile = originalsound->newpackedfile;
336                 sound->panning = originalsound->panning;
337                 sound->pitch = originalsound->pitch;
338                 sound->sample = originalsound->sample;
339                 sound->volume = originalsound->volume;
340                 
341                 if (originalsound->flags & SOUND_FLAGS_3D)
342                         sound->flags |= SOUND_FLAGS_3D;
343                 else
344                         sound->flags &= ~SOUND_FLAGS_3D;
345         }
346         
347         return sound;
348 }
349
350
351
352 void sound_initialize_sample(bSound *sound)
353 {
354         if(ghSoundScene==NULL) sound_init_audio();
355
356         if (sound && sound->sample == NULL)
357                 sound_sample_is_null(sound);
358 }
359
360
361 void sound_read_wav_data(bSound *sound, PackedFile *pf)
362 {
363         int i, temp;
364         short shortbuf, *temps;
365         int longbuf;
366         char buffer[25];
367         char *data = NULL;
368         char *tempc;
369         bSample *sample = NULL;
370         int channels, rate, bits, len;
371         
372         /* prepare for the worst... */
373         sound->sample->type = SAMPLE_INVALID;
374
375         rewindPackedFile(pf);
376
377         /* check to see if it is a file in "RIFF WAVE fmt" format */
378         if (readPackedFile(pf, buffer, 16) != 16) {
379                 if (G.f & G_DEBUG) printf("File too short\n");
380                 return;
381         }
382
383         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8))) {
384                 readPackedFile(pf, &i, 4);// start of data
385                 if(G.order==B_ENDIAN)
386                         SWITCH_INT(i);
387
388                 /* read the sampleformat */
389                 readPackedFile(pf, &shortbuf, 2);
390                 if(G.order==B_ENDIAN) {
391                         SWITCH_SHORT(shortbuf);
392                 }
393
394                 /* read the number of channels */
395                 readPackedFile(pf, &shortbuf, 2);
396
397                 if(G.order==B_ENDIAN) {
398                         SWITCH_SHORT(shortbuf);
399                 }
400
401                 /* check the number of channels */
402                 if(shortbuf != 1 && shortbuf != 2) {
403                         if (G.f & G_DEBUG) printf("Unsupported number of channels\n");
404                         return;
405                 }
406                 channels = shortbuf;
407                 
408                 /* read the samplerate */
409                 readPackedFile(pf, &longbuf, 4);
410
411
412                 if(G.order==B_ENDIAN)
413                         SWITCH_INT(longbuf);
414                 rate = longbuf;
415                 
416                 /* read the bitrate */
417                 // Ton's way
418                 readPackedFile(pf, &temp, 4);
419
420                 if(G.order==B_ENDIAN)
421                         SWITCH_INT(temp);
422
423                 if(channels && rate)
424                         bits= 8*temp/(rate * channels);
425                 
426                 // Frank's way
427
428                 readPackedFile(pf, &shortbuf, 2);
429                 readPackedFile(pf, &shortbuf, 2);
430                 if(G.order==B_ENDIAN) {
431                         SWITCH_SHORT(shortbuf);
432                 }
433                 bits = shortbuf;
434                 
435                 seekPackedFile(pf, i-16, SEEK_CUR);
436                 readPackedFile(pf, buffer, 4);
437                 /* check if we have a 'data' chunk */
438                 while(memcmp(buffer, "data", 4)!=0) {
439                         if (readPackedFile(pf, &i, 4) != 4)
440                                 break;
441                         
442                         if(G.order==B_ENDIAN)
443                                 SWITCH_INT(i);
444
445                         seekPackedFile(pf, i, SEEK_CUR);
446                         if (readPackedFile(pf, buffer, 4) != 4)
447                                 break;
448                 }
449                 
450                 /* guess not */
451                 if (memcmp(buffer, "data", 4) !=0) {
452                         if (G.f & G_DEBUG) printf("No data found\n");
453                 }
454                 /* or maybe we do! */
455                 else {
456                         readPackedFile(pf, &longbuf, 4); 
457                         if(G.order==B_ENDIAN) SWITCH_INT(longbuf);
458                         
459                         /* handle 8 and 16 bit samples differently */
460                         /* intrr: removed, longbuf is length in bytes, not samples */
461                         if (bits == 16)
462                                 data = (char *)MEM_mallocN(longbuf, "sample data");
463                         else 
464                                 data = (char *)MEM_mallocN(longbuf*2, "sample data");
465
466                         len = longbuf /*/ 4.0*/; /* for some strange reason the sample length is off by a factor of 4... */
467                         /* intrr's comment: Funny eh, how one 16-bit stereo sample is 4 bytes? :-) */
468                         
469                         if(data) {
470                                 readPackedFile(pf, data, len);
471                                 /* data is only used to draw! */
472                                 if (bits == 8) {
473                                         temps = (short *) data;
474                                         tempc = (char *) data;
475                                         for (i = len - 1; i >= 0; i--)
476                                                 temps[i] = tempc[i] << 8;
477                                 }
478                                 else {
479                                         if(G.order==B_ENDIAN) {
480                                                 swab(data, data, len);
481                                         }
482                                 }
483                                 /* fill the sound with the found data */
484                                 sample = sound->sample;
485                                 sample->channels = channels;
486                                 sample->rate = rate;
487                                 sample->bits = bits;
488                                 sample->len = len;
489                                 sample->data = data;
490                                 sample->type = SAMPLE_WAV;
491                         }
492                 }
493         }
494         else {
495                 sound->sample->type = SAMPLE_INVALID;
496                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
497         }
498 }
499
500
501
502 /* ugly, but it works (for now) */
503 static int sound_get_filetype_from_header(bSound *sound, PackedFile *pf)
504 {
505         int filetype = SAMPLE_INVALID;
506         int i;
507         char buffer[25];
508         short shortbuf;
509         
510         rewindPackedFile(pf);
511         
512         if (readPackedFile(pf, buffer, 16) != 16) {
513                 if (G.f & G_DEBUG) printf("File too short\n");
514                 return filetype;
515         }
516         
517         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8))) {
518                 readPackedFile(pf, &i, 4);
519                 if(G.order==B_ENDIAN)
520                         SWITCH_INT(i);
521                 
522                 /* read the sampleformat */
523                 readPackedFile(pf, &shortbuf, 2);
524                 if(G.order==B_ENDIAN) {
525                         char s_i, *p_i;
526                         p_i= (char *)&(shortbuf);
527                         s_i= p_i[0];
528                         p_i[0]= p_i[1];
529                         p_i[1]= s_i;
530                 }
531                 
532                 if (shortbuf == SND_WAVE_FORMAT_PCM) {
533                         filetype = SAMPLE_WAV;
534                 }
535                 else
536                         /* only fmod supports compressed wav */
537 #ifdef USE_FMOD
538                 {
539                         /* and only valid publishers may use compressed wav */
540                         switch (shortbuf)
541                         {
542                         case SND_WAVE_FORMAT_ADPCM:
543                         case SND_WAVE_FORMAT_ALAW:
544                         case SND_WAVE_FORMAT_MULAW:
545                         case SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
546                         case SND_WAVE_FORMAT_CONTROL_RES_VQLPC:
547                         case SND_WAVE_FORMAT_GSM_610:
548                         case SND_WAVE_FORMAT_MPEG3:
549                                 filetype = SAMPLE_WAV;
550                                 break;
551                         default:
552 #endif
553                                 {
554                                         filetype = SAMPLE_INVALID;
555                                         if (G.f & G_DEBUG) printf("Unsupported wav compression\n");
556                                 }
557                         }
558 #ifdef USE_FMOD
559                 }
560         }
561         else if (!memcmp(buffer, "OggS", 4)) {
562                 filetype = SAMPLE_OGG_VORBIS;
563         }
564         else if ((!memcmp(buffer, "ID3", 3)) || (!memcmp(buffer, "", 2))) {
565                 filetype = SAMPLE_MP3;
566         }
567 #endif
568         else {
569                 filetype = SAMPLE_INVALID;
570                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
571         }
572         
573         return filetype;
574 }
575
576
577
578 static int check_filetype(bSound *sound, PackedFile *pf)
579 {
580 //      char* pdest;
581         sound->sample->type = SAMPLE_INVALID;
582 /*      
583         // parse the name for the extension to see what kind of sample it is
584         pdest = strrchr(sound->sample->name, '.');
585
586         // a simple check to see what kind of sample we're dealing with
587         if (stricmp(pdest, ".wav") == 0)
588                 sound->sample->type = SAMPLE_WAV;
589
590 #ifdef USE_FMOD
591         if (stricmp(pdest, ".mp2") == 0)
592                 sound->sample->type = SAMPLE_MP2;
593         if (stricmp(pdest, ".mp3") == 0)
594                 sound->sample->type = SAMPLE_MP3;
595         if (stricmp(pdest, ".ogg") == 0)
596                 sound->sample->type = SAMPLE_OGG_VORBIS;
597         if (stricmp(pdest, ".raw") == 0)
598                 sound->sample->type = SAMPLE_RAW;
599         if (stricmp(pdest, ".wma") == 0)
600                 sound->sample->type = SAMPLE_WMA;
601         if (stricmp(pdest, ".asf") == 0)
602                 sound->sample->type = SAMPLE_ASF;
603 #endif
604 */
605         sound->sample->type = sound_get_filetype_from_header(sound, pf);
606
607         /* get some info from the sample */
608         switch (sound->sample->type) {
609         case SAMPLE_WAV:
610                 {
611                         sound_read_wav_data(sound, pf);
612                         break;
613                 }
614         case SAMPLE_OGG_VORBIS:
615         case SAMPLE_MP3:
616         case SAMPLE_MP2:
617         case SAMPLE_RAW:
618         case SAMPLE_WMA:
619         case SAMPLE_ASF:
620                 break;
621         default:
622                 {
623                         if (G.f & G_DEBUG) printf("No valid sample: %s\n", sound->name);
624                         break;
625                 }
626         }
627         
628         return sound->sample->type;
629 }
630
631
632
633 int sound_load_sample(bSound *sound)
634 {
635         int result = FALSE;
636         PackedFile *pf;
637         int freePF = FALSE;
638         int buffer = -1;
639
640         if(ghSoundScene==NULL) sound_init_audio();
641
642         /* check the sample (valid?) */
643         if (sound->sample->type == SAMPLE_UNKNOWN || sound->snd_sound == NULL) {
644                 /* find... */
645                 pf = sound_find_packedfile(sound);
646
647                 /* ...or create a (temp)packedfile */
648                 if (pf == NULL) {
649                         pf = newPackedFile(sound->name);
650                         
651                         /* if autopack is off, free the pf afterwards */
652                         if ((G.fileflags & G_AUTOPACK) == 0)
653                                 freePF = TRUE;
654                 }
655                 
656                 /* if we have a valid pf... */
657                 if (pf) {
658                         /* check the content of the pf */
659                         check_filetype(sound, pf);
660
661                         /* check if the sampletype is supported */
662                         if (sound->sample->type != SAMPLE_INVALID && sound->sample->type != SAMPLE_UNKNOWN) {
663                                 /* register the sample at the audiodevice */
664                                 buffer = SND_AddSample(ghSoundScene, sound->sample->name, pf->data, pf->size);
665
666                                 /* create a soundobject */
667                                 sound->snd_sound = SND_CreateSound();
668                                 SND_SetSampleName(sound->snd_sound, sound->sample->name);
669                                         
670                                 /* add the soundobject to the soundscene  */
671                                 if (SND_CheckBuffer(ghSoundScene, sound->snd_sound))
672                                         SND_AddSound(ghSoundScene, sound->snd_sound);
673                                 else
674                                         if (G.f & G_DEBUG) printf("error: sample didn't load properly\n");
675                                 
676                                 /* if it was places in buffer[0] or higher, it succeeded */
677                                 if (buffer >= 0)
678                                         result = TRUE;
679                         }
680                         /* if not, free the pf */
681                         else {
682                                 freePF = TRUE;
683                         }
684                         
685                         /* if you want it freed, make it so */
686                         if (freePF) {
687                                 freePackedFile(pf);
688                                 pf = NULL;
689                         } 
690                         /* or else connect the pf to the sound and sample */
691 //                      else {
692                                 sound->newpackedfile = pf;
693                                 sound->sample->packedfile = pf;
694 //                      }
695                 }
696                 else  {
697                         if (G.f & G_DEBUG) printf("%s: File not found!\n", sound->name);
698                         sound->sample->type = SAMPLE_INVALID;
699                 }
700         }
701         /* if the sample ain't invalid, we're ready to go! */
702         else if (sound->sample->type != SAMPLE_INVALID) {
703                 result = TRUE;
704         }
705
706         return result;
707 }
708
709
710
711 bSound *sound_new_sound(char *name)
712 {
713         bSound *sound = NULL;
714         int len, file;
715         char str[FILE_MAXDIR+FILE_MAXFILE];
716
717         if(ghSoundScene==NULL) sound_init_audio();
718
719         if (!G.scene->audio.mixrate) G.scene->audio.mixrate = 44100;
720         /* convert the name to absolute path */
721         strcpy(str, name);
722         BLI_convertstringcode(str, G.sce);
723
724         /* check if the sample on disk can be opened */
725         file = open(str, O_BINARY|O_RDONLY);
726         
727         if (file != -1) {
728                 close(file);
729
730
731                 /* do some name magic */
732                 len = strlen(name);
733                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
734                         len--;
735                 
736                 /* allocate some memory for the sound */
737                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
738                 strcpy(sound->name, name);
739                 
740                 /* intialize and check the sample */
741                 sound_initialize_sample(sound);
742
743                 /* load the sample & check if this blender supports the sound format */
744 //              sound_load_sample(sound);
745
746                 if (sound->sample->type == SAMPLE_INVALID) {
747                         free_libblock(&G.main->sound, sound);
748                         sound = NULL;
749                 } 
750                 else
751                 {
752                         sound->volume = 1.0;
753                         sound->attenuation = 1.0;
754                         sound->distance = 1.0;
755                         sound->min_gain = 0.0;
756                         sound->max_gain = 1.0;
757                 }
758         }
759         
760         return (sound);
761 }
762
763
764
765 int sound_set_sample(bSound *sound, bSample *sample)
766 {
767         int result = TRUE;
768         
769         if(ghSoundScene==NULL) sound_init_audio();
770         
771         /* delete the soundobject */
772         if (sound->snd_sound) {
773                 SND_RemoveSound(ghSoundScene, sound->snd_sound);
774                 sound->snd_sound = NULL;
775         }
776
777         /* connect the sample to the sound */
778         sound->sample = sample;
779         sound->newpackedfile = NULL;
780         
781         if (sound->sample) {
782
783                 /* and set the right pf */
784                 sound->newpackedfile = sample->packedfile;
785
786                 /* if the sampletype is unknown initialize it */
787                 if (sound->sample->type == SAMPLE_UNKNOWN) {
788                         sound_initialize_sample(sound);
789                         
790                         /* load the sample & check if this blender supports the sound format */
791                         if (!sound_load_sample(sound)) {
792                                 result = FALSE;
793                         }
794                 }
795         }
796
797         return result;
798 }
799
800
801
802 bSample *sound_new_sample(bSound *sound)
803 {
804         char samplename[FILE_MAX];
805         bSample *sample = NULL;
806         int len;
807         char *name;
808         
809         if (sound != NULL) {
810                 name = sound->name;     
811                 len = strlen(name);
812                 /* do some name magic */
813                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
814                         len--;
815                 
816                 /* allocate the memory for the sample */
817                 sample = MEM_callocN(sizeof(bSample), "sample");
818                 BLI_strncpy(sample->id.name+2, name+len, 20);
819                 BLI_addtail(samples, sample);   /* samples is ugly global */
820                 
821                 sample->data = &sample->fakedata[0];
822                 sample->type = SAMPLE_UNKNOWN;
823                 
824                 /* some default settings. We get divide by zero if these values are not set     */
825                 sample->channels = 1;
826                 sample->rate = 44100;
827                 sample->bits = 16;
828                 sample->alindex = SAMPLE_INVALID;
829
830                 /* convert sound->name to abolute filename */
831                 /* TODO: increase sound->name, sample->name and strip->name to FILE_MAX, to avoid
832                    cutting off sample name here - elubie */
833                 BLI_strncpy(samplename, sound->name, FILE_MAX);         
834                 BLI_convertstringcode(samplename, G.sce);
835                 BLI_strncpy(sample->name, samplename, FILE_MAXDIR);
836
837                 /* connect the pf to the sample */
838                 if (sound->newpackedfile)
839                         sample->packedfile = sound->newpackedfile;
840                 else
841                         sample->packedfile = sound_find_packedfile(sound);
842         }
843         
844         return(sample);
845 }
846
847
848
849 /* find a sample that might already be loaded */
850 bSample *sound_find_sample(bSound *sound)
851 {
852         bSample *sample;
853         char name[FILE_MAXDIR + FILE_MAXFILE];
854         char samplename[FILE_MAXDIR + FILE_MAXFILE];
855         
856         // convert sound->name to abolute filename
857         strcpy(name, sound->name);
858         BLI_convertstringcode(name, G.sce);
859         
860         /* search through the list of loaded samples */
861         sample = samples->first;
862         while (sample) {
863                 strcpy(samplename, sample->name);
864                 BLI_convertstringcode(samplename, G.sce);
865                 
866                 if (strcmp(name, samplename) == 0)      {
867                         break;
868                 }
869                 sample = sample->id.next;
870         }
871         
872         return (sample);
873 }
874
875
876
877 int sound_sample_is_null(bSound *sound)
878 {
879         int result = FALSE;
880         bSample *sample;
881         
882         if(ghSoundScene==NULL) sound_init_audio();
883         
884         /* find the right sample or else create one */
885         if (sound->sample == NULL) {
886                 /* find... */
887                 sample = sound_find_sample(sound);
888
889                 /* or a new one? */
890                 if (sample == NULL)
891                         sample = sound_new_sample(sound);
892                 
893                 if (sound_set_sample(sound, sample))
894                         result = TRUE;
895         }
896
897         return result;
898 }
899
900
901
902 void sound_stop_all_sounds(void)
903 {
904 #if GAMEBLENDER == 1
905         if(ghSoundScene) {
906                 SND_StopAllSounds(ghSoundScene);
907                 SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
908         }
909 #endif 
910 }
911
912
913
914 void sound_end_all_sounds(void)
915 {
916 #if GAMEBLENDER == 1
917         bSound *sound;
918
919         if(ghSoundScene) {
920                 for(sound=G.main->sound.first; sound; sound=sound->id.next) {
921                         if(sound->snd_sound) {
922                                 SND_RemoveSound(ghSoundScene, sound->snd_sound);
923                                 sound->snd_sound = NULL;
924                         }
925                 }
926
927                 sound_stop_all_sounds();
928                 SND_RemoveAllSounds(ghSoundScene);
929         }
930 #endif
931 }
932
933
934
935 void sound_play_sound(bSound *sound)
936 {
937 #if GAMEBLENDER == 1
938         if(ghSoundScene==NULL) sound_init_audio();
939         
940         /* first check if we want sound or not */
941         SND_IsPlaybackWanted(ghSoundScene);
942
943         /* stop all previous sounds */
944         SND_StopAllSounds(ghSoundScene);
945         
946         if (sound != NULL && sound->sample != NULL)
947         {
948                 /* load the sample if needed */
949                 if (sound_load_sample(sound))
950                 {
951                         /* set all kinds of parameters */
952                         SND_SetListenerGain(ghSoundScene, G.listener->gain);
953                         SND_SetDopplerFactor(ghSoundScene, G.listener->dopplerfactor);
954                         SND_SetDopplerVelocity(ghSoundScene, G.listener->dopplervelocity);
955                         
956                         SND_SetGain((SND_ObjectHandle)sound->snd_sound, (sound->volume));
957                         SND_SetPitch((SND_ObjectHandle)sound->snd_sound, (exp((sound->pitch / 12.0) * log(2.0))));
958                         
959                         if (sound->flags & SOUND_FLAGS_LOOP)
960                         {
961                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
962 #ifdef SOUND_UNDER_DEVELOPMENT
963 /*                              SND_SetLoopPoints((SND_ObjectHandle)sound->snd_sound, sound->loopstart, sound->loopend);
964 */
965 #endif
966                                 if (sound->flags & SOUND_FLAGS_BIDIRECTIONAL_LOOP)
967                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_BIDIRECTIONAL);
968                                 else
969                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
970
971                         }
972                         else 
973                         {
974                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_OFF);
975                         }
976                         
977                         if (sound->flags & SOUND_FLAGS_3D)
978                         {
979                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, sound->attenuation);
980                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, sound->distance);
981                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, sound->min_gain);
982                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, sound->max_gain);
983                         }
984                         else
985                         {
986                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, 0);
987                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, 1);
988                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, 1);
989                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, 1);
990                         }
991                         
992                         if (G.f & G_DEBUG) printf("Set pitch to: %f\n", SND_GetPitch((SND_ObjectHandle)sound->snd_sound));
993                         if (G.f & G_DEBUG) printf("Set gain to: %f\n", SND_GetGain((SND_ObjectHandle)sound->snd_sound));
994                         if (G.f & G_DEBUG) printf("Set looping to: %d\n", SND_GetLoopMode((SND_ObjectHandle)sound->snd_sound));
995                         
996                         /* play the sound */
997                         SND_StartSound(ghSoundScene, (SND_ObjectHandle)sound->snd_sound);
998
999                         /* update the device */
1000                         SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
1001                 }
1002         }
1003         else 
1004         {
1005                 if (G.f & G_DEBUG)
1006                 {
1007                         printf("uninitialized sound !\n");              
1008                         if (sound)
1009                         {
1010                                 printf("sound: %p\n", sound);
1011                                 if (sound->sample)
1012                                 {
1013                                         printf("sample: %p\n", sound->sample);
1014                                         if (sound->snd_sound)
1015                                                 printf("hSoundObject: %p\n", sound->snd_sound);
1016                                 }
1017                         }
1018                         else
1019                         {
1020                                 printf("sound == NULL\n");
1021                         }
1022                 }
1023         }
1024 #endif 
1025 }
1026
1027
1028
1029 bSound *sound_find_sound(char *id_name)
1030 {
1031         bSound *sound;
1032         
1033         // look for sound with same *id* name
1034         sound = G.main->sound.first;
1035         while (sound)
1036         {
1037                 if (strcmp(sound->id.name + 2, id_name) == 0)
1038                         break;
1039
1040                 sound = sound->id.next;
1041         }
1042         
1043         return sound;
1044 }
1045
1046 void sound_init_audio(void)
1047 {
1048         int noaudio;
1049         SYS_SystemHandle hSystem = NULL;
1050         
1051         if(ghSoundScene==NULL) {
1052                 hSystem = SYS_GetSystem();
1053                 noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0);
1054                 
1055                 if (noaudio)/*(noaudio) intrr: disable game engine audio (openal) */
1056                         SND_SetDeviceType(snd_e_dummydevice);
1057         
1058                 ghAudioDeviceInterface = SND_GetAudioDevice();
1059                 ghSoundScene = SND_CreateScene(ghAudioDeviceInterface);
1060                 // also called after read new file, but doesnt work when no audio initialized
1061                 sound_initialize_sounds();
1062         }
1063 }
1064
1065
1066 int sound_get_mixrate(void)
1067 {
1068         return MIXRATE;
1069 }
1070
1071
1072 void sound_exit_audio(void)
1073 {
1074         if(ghSoundScene) {
1075                 SND_DeleteScene(ghSoundScene);
1076                 SND_ReleaseDevice();
1077                 ghSoundScene = NULL;
1078         }
1079 }