Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://wormux-debuginfo-0.7.9-6.fc9.ppc.rpm:5413035/usr/src/debug/wormux-0.7.9/src/sound/jukebox.cpp  info  downloads

/******************************************************************************
 *  Wormux is a convivial mass murder game.
 *  Copyright (C) 2001-2004 Lawrence Azzoug.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 ******************************************************************************
 * Sound engine
 *****************************************************************************/

#include "jukebox.h"
#include <iostream>
#include <fstream>

#include "../game/config.h"
#include "../tool/debug.h"
#include "../tool/i18n.h"
#include "../tool/random.h"
#include "../tool/file_tools.h"

JukeBox jukebox;

JukeBox::JukeBox()
	: music(0), m_init(false)
{
  m_config.music = true;
  m_config.effects = true;
  m_config.frequency = 44100; //MIX_DEFAULT_FREQUENCY;
  m_config.channels = 2; // stereo
}

void JukeBox::Pause()
{
  Mix_Pause(-1);
}

void JukeBox::Resume()
{
  Mix_Resume(-1);
}

void JukeBox::Init()
{
  if (!m_config.music && !m_config.effects) {
    End();
    return;
  }

  if (m_init) return;

  Uint16 audio_format = MIX_DEFAULT_FORMAT;

  /* Initialize the SDL library */
  if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
    std::cerr << "* Couldn't initialize SDL: "<< SDL_GetError() << std::endl;
    return;
  }

  int audio_buffer = 1024;

  /* Open the audio device */
  if (Mix_OpenAudio(m_config.frequency, audio_format, m_config.channels, audio_buffer) < 0) {
    std::cerr << "* Couldn't open audio: " <<  SDL_GetError() << std::endl;
    return;
  } else {
    Mix_QuerySpec(&m_config.frequency, &audio_format, &m_config.channels);
    std::cout << "o Opened audio at " << m_config.frequency <<" Hz "<< (audio_format&0xFF)
	      <<" bit " << std::endl;
  }
  Mix_ChannelFinished(JukeBox::EndChunk);
  Mix_HookMusicFinished(JukeBox::EndMusic);

  m_init = true;

  LoadXML("share");
  LoadMusicXML();
}

void JukeBox::End()
{
  if (!m_init) return;

  StopAll();
  StopMusic();

  m_soundsamples.clear();
  m_profiles_loaded.clear();
  playlist.clear();

  Mix_CloseAudio();

  m_init = false;
}

void JukeBox::SetFrequency (int frequency)
{
  if ((frequency != 11025)
      && (frequency != 22050)
      && (frequency != 44100)) frequency = 44100;

  if (m_config.frequency == frequency) return;

  m_config.frequency = frequency;

  // Close and reopen audio device
  End();
  Init();
}

// Code not used
#if 0
void JukeBox::SetNumbersOfChannel(int channels)
{
  if (m_config.channels == channels) return;

  m_config.channels = channels;

  // Close and reopen audio device
  End();
  Init();
}
#endif

void JukeBox::ActiveMusic (bool on)
{
   if(IsPlayingMusic() && !on)
      StopMusic();
   m_config.music = on;
}

void JukeBox::LoadMusicXML()
{
  // is xml_file already loaded ?
  std::set<std::string>::iterator it_profile = m_profiles_loaded.find("music") ;
  if (it_profile !=  m_profiles_loaded.end()) {
	  MSG_DEBUG("jukebox", "Music is already loaded !");
      return;
  }
  std::cout << "o Loading music" << std::endl;

  XmlReader doc;

  // Load the XML
  std::string folder = Config::GetInstance()->GetDataDir() + PATH_SEPARATOR + "music" + PATH_SEPARATOR;
  std::string xml_filename = folder + "profile.xml";
  if( !IsFileExist(xml_filename) ){
    std::cerr << "[Music] Error : file " << xml_filename << " not found" << std::endl;
    return;
  }
  if(!doc.Load(xml_filename))
    return;

  xmlpp::Node::NodeList nodes = doc.GetRoot()->get_children("music");
  xmlpp::Node::NodeList::iterator
    it=nodes.begin(),
    fin=nodes.end();

  for (; it != fin; ++it)
    {
      // lit le XML
      xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it);
      std::string sample="no_sample";
      std::string file="no_file";
      XmlReader::ReadStringAttr(elem, "type", sample);
      XmlReader::ReadStringAttr(elem, "playlist", file);

      MSG_DEBUG("jukebox", "Load music sample %s", sample.c_str());

      // Charge le son
      std::string filename = folder + file;
      if( !IsFileExist(filename) ){
        std::cerr << "Music error: File " << filename.c_str()
                  << " does not exist !" << std::endl;
	continue;
      }

      std::ifstream fp(filename.c_str());
      std::string line;

      while(std::getline(fp, line))
      {
         if(line[0] == '#') continue;

         if(!IsFileExist(line))
         {
            line = filename.substr(0, filename.find_last_of(PATH_SEPARATOR)) + PATH_SEPARATOR + line;
            if(!IsFileExist(line))
            {
              std::cerr << "[Music] Unable to find " << line << " music file." << std::endl;
              continue;
            }
         }
         playlist[sample].push_back(line);
      }
    }

  // The profile is loaded
  m_profiles_loaded.insert("music");
  playing_pl = playlist.end();
}

void JukeBox::EndMusic()
{
  if(!jukebox.music)
     return;

  Mix_FreeMusic(jukebox.music);
  jukebox.music = 0;

  if(!jukebox.UseMusic() || !jukebox.IsPlayingMusic())
     return;

  if((jukebox.playing_music+1) == jukebox.playing_pl->second.end())
    jukebox.playing_music = jukebox.playing_pl->second.begin();
  else
    ++jukebox.playing_music;

  jukebox.PlayMusicSample(jukebox.playing_music);

  return;
}

void JukeBox::StopMusic()
{
   if(!IsPlayingMusicSample())
      return;
   playing_music = playing_pl->second.end();
   playing_pl = playlist.end();
   Mix_HaltMusic();
   EndMusic();
}

void JukeBox::NextMusic()
{
   if(!IsPlayingMusic())
     return;
   else if(!IsPlayingMusicSample())
      PlayMusic(playing_pl->first);
   else
      EndMusic(); // On passe à la musique suivante par l'arrêt de celle-ci
}

bool JukeBox::PlayMusic(const std::string& type)
{
  if(m_init == false || !UseMusic()) return false;

  PlayListMap::iterator it = playlist.find(type);

  if(it == playlist.end())
  {
     std::cerr << "[Music] Unable to find " << type << " profile" << std::endl;
     return false;
  }

  MSG_DEBUG("jukebox", "Loading playlist %s", type.c_str());

  StopMusic();

  if(it->second.empty() || !UseMusic()) return false;

  playing_pl = it;

  int i, j = 0;
  do
  {
     i = rand()%it->second.size();
     j++;
  } while(!PlayMusicSample(it->second.begin()+i) && j < 10); // After 10 times, we think there is a problem.

  if(j >= 10)
     playing_pl = playlist.end();

  return (j < 10);
}

bool JukeBox::PlayMusicSample(std::vector<std::string>::const_iterator file_it)
{
   if(!UseMusic() || !m_init) return false;

   std::string file = *file_it;

   if(music)
      Mix_FreeMusic(music);

   music = Mix_LoadMUS(file.c_str());

   MSG_DEBUG("jukebox", "We trying to load music %s", file.c_str());

   if(!music || Mix_PlayMusic(music, 0) < 0)
   {
      std::cerr << "[Music] Error : Unable to load music " << file << std::endl;
      playing_music = playing_pl->second.end();
      return false;
   }

   playing_music = file_it;
   return true;
}

void JukeBox::LoadXML(const std::string& profile)
{
  // is xml_file already loaded ?
  std::set<std::string>::iterator it_profile = m_profiles_loaded.find(profile) ;
  if (it_profile !=  m_profiles_loaded.end()) {
	  MSG_DEBUG("jukebox", "Profile %s is already loaded !", profile.c_str());
      return;
  }
  std::cout << "o Loading sound profile " << profile << std::endl;

  XmlReader doc;

  // Load the XML
  std::string folder = Config::GetInstance()->GetDataDir() + PATH_SEPARATOR + "sound"+ PATH_SEPARATOR + profile + PATH_SEPARATOR;
  std::string xml_filename = folder + "profile.xml";
  if( !IsFileExist(xml_filename) ){
    std::cerr << "[Sound] Error : file " << xml_filename << " not found" << std::endl;
    return;
  }
  if(!doc.Load(xml_filename))
    return;

  xmlpp::Node::NodeList nodes = doc.GetRoot()->get_children("sound");
  xmlpp::Node::NodeList::iterator
    it=nodes.begin(),
    fin=nodes.end();

  for (; it != fin; ++it)
    {
      // lit le XML
      xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it);
      std::string sample="no_sample";
      std::string file="no_file";
      XmlReader::ReadStringAttr(elem, "sample", sample);
      XmlReader::ReadStringAttr(elem, "file", file);

	  MSG_DEBUG("jukebox", "Load sound sample %s/%s: %s", profile.c_str(), sample.c_str(), file.c_str());

      // Charge le son
      std::string sample_filename = folder + file;
      if( !IsFileExist(sample_filename) ){
	std::cerr << "Sound error: File " << sample_filename.c_str()
		  << " does not exist !" << std::endl;
	continue;
      }

      // Inserting sound sample in list
      m_soundsamples.insert(sound_sample(profile+"/"+sample, sample_filename));
    }

  // The profile is loaded
  m_profiles_loaded.insert(profile);
}

int JukeBox::Play (const std::string& category, const std::string& sample,
		   const int loop)
{
  if (!UseEffects()) return -1;

  uint nb_sons= m_soundsamples.count(category+"/"+sample);
  if (nb_sons)
  {
    std::pair<sample_iterator, sample_iterator> p = m_soundsamples.equal_range(category+"/"+sample);
    sample_iterator it = p.first;

    // Choose a random sound sample
    if (nb_sons > 1)
    {
      uint selection = uint(randomObj.GetLong(0, nb_sons));
      if (selection == nb_sons) --selection ;

      it = p.first ;

      for ( uint i=0 ; i<selection && it!=p.second ; ++i ) it++ ;
    }

    // Play the sound
    Mix_Chunk * sampleChunk = Mix_LoadWAV(it->second.c_str());
    MSG_DEBUG("jukebox.play", "Playing sample %s/%s", category.c_str(), sample.c_str());
    return PlaySample(sampleChunk, loop);
  }
  else if (category != "default") { // try with default profile
    return Play("default", sample, loop) ; // try with default profile
  }

  MSG_DEBUG("jukebox", "Error: No sound found for sample %s/%s", category.c_str(), sample.c_str());
  return -1;
}

int JukeBox::Stop (int channel)
{
  if(!m_config.music && !m_config.effects) return 0;
  if (channel == -1) return 0;
  return Mix_HaltChannel(channel);
}

int JukeBox::StopAll()
{
  if (!m_config.music && !m_config.effects) return 0;

  // halt playback on all channels
  return Mix_HaltChannel(-1);
}

int JukeBox::PlaySample (Mix_Chunk * sample, int loop)
{
  if (loop != -1) loop--;

  int channel = Mix_PlayChannel(-1, sample, loop);

  if (channel == -1) {
	MSG_DEBUG("jukebox", "Error: Jukebox::PlaySample: %s", Mix_GetError());
	Mix_FreeChunk(sample);
  }
  else
    chunks[channel] = sample;
  return channel;
}

void JukeBox::EndChunk(int channel)
{
  Mix_Chunk* chk = jukebox.chunks[channel];

  if(!chk) return;

  Mix_FreeChunk(chk);
  jukebox.chunks[channel] = 0;
}
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2008 IT MARUHN