text: /*
   * This file is part of the Simutrans project under the Artistic License.
   * (see LICENSE.txt)
   */
  
  #include <string>
  #include <stdio.h>
  #include "../simdebug.h"
  
  #include "../dataobj/tabfile.h"
  #include "../dataobj/environment.h"
  
  #include "../macros.h"
  #include "../sound/sound.h"
  
  #include "../utils/simstring.h"
  
  #include "../tpl/stringhashtable_tpl.h"
  
  #include "spezial_obj_tpl.h"
  #include "sound_desc.h"
  #include "ground_desc.h"
  
  /*
   * sound of the program
   */
  class sound_ids {
  public:
  	std::string filename;
  	sint16 id;
  	sound_ids() { id=NO_SOUND; }
  	sound_ids(sint16 i) { id=i;  }
  	sound_ids(sint16 i, const char* fn) : filename(fn), id(i) {}
  };
  
  
  static stringhashtable_tpl<sound_ids *> name_sound;
  static bool sound_on=false;
  static std::string sound_path;
  
  sint16 sound_desc_t::compatible_sound_id[MAX_OLD_SOUNDS]=
  {
  	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
  	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
  	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
  	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND
  };
  
  // sound with the names of climates and "beach" and "forest" are reserved for ambient noises
  sint16 sound_desc_t::beach_sound = NO_SOUND;
  sint16 sound_desc_t::forest_sound = NO_SOUND;
  sint16 sound_desc_t::climate_sounds[MAX_CLIMATES]=
  {
  	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
  	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND
  };
  
  
  /* init sounds */
  /* standard sounds and old sounds are found in the file pak/sound/sound.tab */
  void sound_desc_t::init()
  {
  	// ok, now init
  	sound_on = true;
  	sound_path = env_t::data_dir;
  	sound_path= sound_path + env_t::objfilename + "sound/";
  	// process sound.tab
  	tabfile_t soundconf;
  	if (soundconf.open((sound_path + "sound.tab").c_str())) {
  DBG_MESSAGE("sound_desc_t::init()","successfully opened sound/sound.tab"  );
  		tabfileobj_t contents;
  		soundconf.read(contents);
  		// max. 16 old sounds ...
  		for( unsigned i=0;  i<MAX_OLD_SOUNDS;  i++ ) {
  			char buf[1024];
  			sprintf(buf, "sound[%i]", i);
  			const char *fn=ltrim(contents.get(buf));
  			if(fn[0]>0) {
  DBG_MESSAGE("sound_desc_t::init()","reading sound %s", fn  );
  				compatible_sound_id[i] = get_sound_id( fn );
  DBG_MESSAGE("sound_desc_t::init()","assigned system sound %d to sound %s (id=%i)", i, (const char *)fn, compatible_sound_id[i] );
  			}
  		}
  		// now assign special sounds for climates, beaches and forest
  		beach_sound = get_sound_id( "beaches.wav" );
  		forest_sound = get_sound_id( "forest.wav" );
  		for(  int i=0;  i<MAX_CLIMATES;  i++  ) {
  			char name[64];
  			sprintf( name, "%s.wav", ground_desc_t::get_climate_name_from_bit((climate)i) );
  			climate_sounds[i] = get_sound_id( name );
  		}
  	}
  }
  
  
  
  
  /* return sound id from index */
  sint16 sound_desc_t::get_sound_id(const char *name)
  {
  	if(  !sound_on  ||  name==NULL  ||  *name==0  ) {
  		return NO_SOUND;
  	}
  
  	sound_ids *s = name_sound.get(name);
  	if(s!=NULL  &&  s->id!=NO_SOUND) {
  		DBG_MESSAGE("sound_desc_t::get_sound_id()", "Successfully retrieved sound \"%s\" with internal id %hi", s->filename.c_str(), s->id );
  		return s->id;
  	}
  
  	// not loaded: try to load it
  	const sint16 sample_id = dr_load_sample((sound_path + name).c_str());
  
  	if(sample_id==NO_SOUND) {
  		dbg->warning("sound_desc_t::get_sound_id()", "Sound \"%s\" not found", name );
  		return NO_SOUND;
  	}
  
  	s = new sound_ids(sample_id, name);
  	name_sound.put(s->filename.c_str(), s );
  DBG_MESSAGE("sound_desc_t::get_sound_id()", "Successfully loaded sound \"%s\" with internal id %hi", s->filename.c_str(), s->id );
  	return s->id;
  }
  
  
  
  /*
   * if there is already such a sound => fail, else success and get an internal sound id
   * do not store desc as it will be deleted anyway
   */
  bool sound_desc_t::register_desc(sound_desc_t *desc)
  {
  	if(  !sound_on  ) {
  		return false;
  	}
  
  	// register, if not there (all done by this one here)
  	desc->sound_id = get_sound_id( desc->get_name() );
  	if(desc->sound_id!=NO_SOUND) {
  		if(desc->nr>=0  &&  desc->nr<=8) {
  			compatible_sound_id[desc->nr] = desc->sound_id;
  DBG_MESSAGE("sound_desc_t::register_desc", "Successfully registered sound %s internal id %i as compatible sound %i", desc->get_name(), desc->sound_id, desc->nr );
  			return true;
  		}
  	}
  
  	dbg->warning("sound_desc_t::register_desc", "Failed to register sound %s internal id %i", desc->get_name(), desc->sound_id);
  	return false;
  }
  