DEADSOFTWARE

fixed music (all sounds, actually) muting after exiting in-game menu (stupid double...
[d2df-sdl.git] / src / engine / e_sound.pas
index f7b208969a9d58453439983388bebbcc30852573..857101a017105c165b4ecdb5bd8db29e9533cd20 100644 (file)
@@ -104,17 +104,56 @@ var
 
 procedure chanFinished (chan: Integer); cdecl;
 begin
+  //e_WriteLog(Format('chanFinished: %d', [chan]), MSG_NOTIFY);
   if (chan >= 0) and (chan < N_CHANNELS) then
   begin
     if ChanSIds[chan].id <> NO_SOUND_ID then
     begin
-      Dec(e_SoundsArray[ChanSIds[chan].id].nRefs);
+      if (ChanSIds[chan].id <= High(e_SoundsArray)) and (e_SoundsArray[ChanSIds[chan].id].nRefs > 0) then
+      begin
+        Dec(e_SoundsArray[ChanSIds[chan].id].nRefs);
+      end;
       ChanSIds[chan].id := NO_SOUND_ID;
     end;
   end;
 end;
 
 
+procedure dumpMusicType (ms: PMix_Music);
+begin
+  if ms = nil then
+  begin
+    e_WriteLog('MUSIC FORMAT: NONE', MSG_NOTIFY);
+  end
+  else
+  begin
+    case Mix_GetMusicType(ms^) of
+      TMix_MusicType.MUS_NONE:
+        e_WriteLog('MUSIC FORMAT: NONE', MSG_NOTIFY);
+      TMix_MusicType.MUS_CMD:
+        e_WriteLog('MUSIC FORMAT: CMD', MSG_NOTIFY);
+      TMix_MusicType.MUS_WAV:
+        e_WriteLog('MUSIC FORMAT: WAV', MSG_NOTIFY);
+      TMix_MusicType.MUS_MOD:
+        e_WriteLog('MUSIC FORMAT: MOD', MSG_NOTIFY);
+      TMix_MusicType.MUS_MID:
+        e_WriteLog('MUSIC FORMAT: MID', MSG_NOTIFY);
+      TMix_MusicType.MUS_OGG:
+        e_WriteLog('MUSIC FORMAT: OGG', MSG_NOTIFY);
+      TMix_MusicType.MUS_MP3:
+        e_WriteLog('MUSIC FORMAT: MP3', MSG_NOTIFY);
+      TMix_MusicType.MUS_MP3_MAD:
+        e_WriteLog('MUSIC FORMAT: MP3_MAD', MSG_NOTIFY);
+      TMix_MusicType.MUS_FLAC:
+        e_WriteLog('MUSIC FORMAT: FLAC', MSG_NOTIFY);
+      TMix_MusicType.MUS_MODPLUG:
+        e_WriteLog('MUSIC FORMAT: MODPLUG', MSG_NOTIFY);
+      otherwise
+        e_WriteLog('MUSIC FORMAT: UNKNOWN', MSG_NOTIFY);
+    end;
+  end;
+end;
+
 function e_InitSoundSystem(): Boolean;
 var
   res, i: Integer;
@@ -124,17 +163,19 @@ begin
   Result := False;
   SoundInitialized := False;
 
-{ // wow, this is actually MIDI player!
+  // wow, this is actually MIDI player!
   // we need module player
-  if (Mix_Init(MIX_INIT_MOD) and MIX_INIT_MOD) <> MIX_INIT_MOD then
-  begin
-    e_WriteLog('Error initializing SDL module player:', MSG_FATALERROR);
-    e_WriteLog(Mix_GetError(), MSG_FATALERROR);
-    //Exit;
-  end;
-}
-
-  res := Mix_OpenAudio(44100, AUDIO_S16LSB, 2, 512);
+  res := Mix_Init(MIX_INIT_FLAC or MIX_INIT_MOD or MIX_INIT_MODPLUG or MIX_INIT_MP3 or MIX_INIT_OGG or MIX_INIT_FLUIDSYNTH);
+  e_WriteLog(Format('SDL: res=0x%x', [res]), MSG_NOTIFY);
+  if (res and MIX_INIT_FLAC) <> 0 then e_WriteLog('SDL: FLAC playback is active', MSG_NOTIFY);
+  if (res and MIX_INIT_MOD) <> 0 then e_WriteLog('SDL: MOD playback is active', MSG_NOTIFY);
+  if (res and MIX_INIT_MODPLUG) <> 0 then e_WriteLog('SDL: MODPLUG playback is active', MSG_NOTIFY);
+  if (res and MIX_INIT_MP3) <> 0 then e_WriteLog('SDL: MP3 playback is active', MSG_NOTIFY);
+  if (res and MIX_INIT_OGG) <> 0 then e_WriteLog('SDL: OGG playback is active', MSG_NOTIFY);
+  if (res and MIX_INIT_FLUIDSYNTH) <> 0 then e_WriteLog('SDL: FLUIDSYNTH playback is active', MSG_NOTIFY);
+
+  res := Mix_OpenAudio(48000, AUDIO_S16LSB, 2, 2048);
+  if res = -1 then res := Mix_OpenAudio(44100, AUDIO_S16LSB, 2, 2048);
   if res = -1 then
   begin
     e_WriteLog('Error initializing SDL mixer:', MSG_FATALERROR);
@@ -199,18 +240,35 @@ begin
     Result := High(e_SoundsArray) + 1;
     SetLength(e_SoundsArray, Length(e_SoundsArray) + 16);
   end;
+  for i := Result to High(e_SoundsArray) do
+  begin
+    e_SoundsArray[i].Sound := nil;
+    e_SoundsArray[i].Music := nil;
+    e_SoundsArray[i].Data := nil;
+    e_SoundsArray[i].isMusic := False;
+    e_SoundsArray[i].nRefs := 0;
+  end;
 end;
 
 function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean): Boolean;
 var
   find_id: DWORD;
 begin
+  ID := NO_SOUND_ID;
   Result := False;
   if not SoundInitialized then Exit;
 
   if isMusic then e_WriteLog('Loading music '+FileName+'...', MSG_NOTIFY)
   else e_WriteLog('Loading sound '+FileName+'...', MSG_NOTIFY);
 
+  {
+  if isMusic then
+  begin
+    e_WriteLog('IGNORING MUSIC FROM FILE', MSG_WARNING);
+    Exit;
+  end;
+  }
+
   find_id := FindESound();
 
   e_SoundsArray[find_id].Data := nil;
@@ -219,8 +277,15 @@ begin
 
   if isMusic then
   begin
+    e_WriteLog(Format('  MUSIC SLOT: %u', [find_id]), MSG_NOTIFY);
     e_SoundsArray[find_id].Music := Mix_LoadMUS(PAnsiChar(FileName));
-    if e_SoundsArray[find_id].Music = nil then Exit;
+    if e_SoundsArray[find_id].Music = nil then
+    begin
+      e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), MSG_WARNING);
+      e_WriteLog(Mix_GetError(), MSG_WARNING);
+      Exit;
+    end;
+    dumpMusicType(e_SoundsArray[find_id].Music);
   end
   else
   begin
@@ -237,9 +302,34 @@ function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic:
 var
   find_id: DWORD;
   rw: PSDL_RWops;
+  //pc: PChar;
+  isid3: Boolean;
 begin
+  ID := NO_SOUND_ID;
   Result := False;
   if not SoundInitialized then Exit;
+  isid3 := False;
+
+  {
+  if isMusic then
+  begin
+    e_WriteLog('IGNORING MUSIC FROM MEMORY', MSG_WARNING);
+    Exit;
+  end;
+  }
+
+  //FIXME: correctly skip ID3
+  {
+  pc := PChar(pData);
+  if (Length > $400) and (pc[0] = 'I') and (pc[1] = 'D') and (pc[2] = '3') then
+  begin
+    isid3 := True;
+    Inc(pc, $400);
+    pData := Pointer(pc);
+    Dec(Length, $400);
+    e_WriteLog('MUSIC: MP3 ID3 WORKAROUND APPLIED!', MSG_WARNING);
+  end;
+  }
 
   rw := SDL_RWFromConstMem(pData, Length);
   if rw = nil then Exit;
@@ -247,19 +337,43 @@ begin
   find_id := FindESound();
 
   e_SoundsArray[find_id].Data := pData;
+  if isid3 then e_SoundsArray[find_id].Data := nil;
   e_SoundsArray[find_id].isMusic := isMusic;
   e_SoundsArray[find_id].nRefs := 0;
 
   if isMusic then
   begin
+    e_WriteLog(Format('  MUSIC SLOT: %u', [find_id]), MSG_NOTIFY);
     e_SoundsArray[find_id].Music := Mix_LoadMUS_RW(rw, 0);
+    if e_SoundsArray[find_id].Music = nil then
+    begin
+      e_WriteLog(Format('ERROR LOADING MUSIC:', [find_id]), MSG_WARNING);
+      e_WriteLog(Mix_GetError(), MSG_WARNING);
+    end
+    else
+    begin
+      dumpMusicType(e_SoundsArray[find_id].Music);
+    end;
+    //SDL_FreeRW(rw);
+    {
+    if e_SoundsArray[find_id].Music <> nil then
+    begin
+      Mix_FreeMusic(e_SoundsArray[find_id].Music);
+    end;
+    e_SoundsArray[find_id].Music := nil;
+    Exit;
+    }
   end
   else
   begin
     e_SoundsArray[find_id].Sound := Mix_LoadWAV_RW(rw, 0);
   end;
-  SDL_FreeRW(rw);
-  if (e_SoundsArray[find_id].Sound = nil) and (e_SoundsArray[find_id].Music = nil) then Exit;
+  //SDL_FreeRW(rw); // somehow it segfaults...
+  if (e_SoundsArray[find_id].Sound = nil) and (e_SoundsArray[find_id].Music = nil) then
+  begin
+    e_SoundsArray[find_id].Data := nil;
+    Exit;
+  end;
 
   ID := find_id;
 
@@ -294,6 +408,7 @@ begin
   else
   begin
     if not e_isMusic(ID) then Exit;
+    Mix_HaltMusic();
     res := Mix_PlayMusic(e_SoundsArray[ID].Music, -1);
     if res >= 0 then res := N_MUSCHAN;
     if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
@@ -385,6 +500,7 @@ procedure e_DeleteSound(ID: DWORD);
 var
   i: Integer;
 begin
+  if ID > High(e_SoundsArray) then Exit;
   if (e_SoundsArray[ID].Sound = nil) and (e_SoundsArray[ID].Music = nil) then Exit;
 
   for i := 0 to N_CHANNELS-1 do
@@ -396,9 +512,9 @@ begin
     end;
   end;
 
-  if e_SoundsArray[ID].Data <> nil then FreeMem(e_SoundsArray[ID].Data);
   if e_SoundsArray[ID].Sound <> nil then Mix_FreeChunk(e_SoundsArray[ID].Sound);
   if e_SoundsArray[ID].Music <> nil then Mix_FreeMusic(e_SoundsArray[ID].Music);
+  if e_SoundsArray[ID].Data <> nil then FreeMem(e_SoundsArray[ID].Data);
 
   e_SoundsArray[ID].Sound := nil;
   e_SoundsArray[ID].Music := nil;
@@ -462,6 +578,7 @@ begin
       if ChanSIds[i].muted then Mix_Volume(i, 0) else Mix_Volume(i, ChanSIds[i].oldvol);
     end;
   end;
+  //if SoundMuted then e_WriteLog('muting music', MSG_NOTIFY) else e_WriteLog(Format('unmuting music (%d)', [MusVolume]), MSG_NOTIFY);
   if SoundMuted then Mix_VolumeMusic(0) else Mix_VolumeMusic(MusVolume);
 end;
 
@@ -548,6 +665,7 @@ begin
   if (FID = NO_SOUND_ID) or not SoundInitialized then Exit;
   FChanNum := e_PlaySoundPanVolume(FID, Pan, Volume);
   Result := (FChanNum >= 0);
+  //if e_isMusic(FID) then e_WriteLog(Format('playing music (%u)', [FID]), MSG_NOTIFY);
   //TODO: aPos
 end;
 
@@ -555,7 +673,10 @@ procedure TBasicSound.SetID(ID: DWORD);
 begin
   FreeSound();
   FID := ID;
-  FMusic := e_SoundsArray[ID].isMusic;
+  if ID <> NO_SOUND_ID then
+  begin
+    FMusic := e_SoundsArray[ID].isMusic;
+  end;
   FChanNum := -1;
 end;
 
@@ -625,6 +746,7 @@ var
   chan: Integer;
   pl: Boolean;
 begin
+  Enable := not Enable; // fuckin' double negation
   if e_isSound(FID) then
   begin
     chan := Channel;