The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
soundsource.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2016 by Karol Nowak <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "global.hpp"
16 
17 
18 #include "display.hpp"
19 #include "log.hpp"
21 #include "sound.hpp"
22 #include "soundsource.hpp"
23 
24 #include <SDL.h> // Travis doesn't like this, although it works on my machine -> '#include <SDL_sound.h>
25 
26 namespace soundsource {
27 
28 const unsigned DEFAULT_CHANCE = 100;
29 const unsigned DEFAULT_DELAY = 1000;
30 
31 unsigned int positional_source::last_id = 0;
32 
33 manager::manager(const display &disp) :
34  observer(),
35  sources_(),
36  disp_(disp)
37 {
40 }
41 
43 {
44  for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) {
45  delete (*it).second;
46  }
47 
48  sources_.clear();
49 }
50 
52 {
53  if(event_name == "scrolled")
55 }
56 
57 void manager::add(const sourcespec &spec)
58 {
60 
61  if((it = sources_.find(spec.id())) == sources_.end()) {
62  sources_[spec.id()] = new positional_source(spec);
63  } else {
64  delete (*it).second;
65  (*it).second = new positional_source(spec);
66  }
67 }
68 
70 {
71  config cfg;
73  if(it != sources_.end()) {
74  it->second->write_config(cfg);
75  }
76  return cfg;
77 }
78 
80 {
82 
83  if((it = sources_.find(id)) == sources_.end())
84  return;
85  else {
86  delete (*it).second;
87  sources_.erase(it);
88  }
89 }
90 
92 {
93  unsigned int time = SDL_GetTicks();
94 
95  for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) {
96  (*it).second->update(time, disp_);
97  }
98 }
99 
101 {
102  unsigned int time = SDL_GetTicks();
103 
104  for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) {
105  (*it).second->update_positions(time, disp_);
106  }
107 }
108 
110 {
111  for(positional_source_const_iterator i = sources_.begin(); i != sources_.end(); ++i) {
112  assert(i->second);
113 
114  config& child = cfg.add_child("sound_source");
115  child["id"] = i->first;
116  i->second->write_config(child);
117  }
118 }
119 
121  last_played_(0),
122  min_delay_(spec.minimum_delay()),
123  chance_(spec.chance()),
124  loops_(spec.loops()),
125  id_(last_id++),
126  range_(spec.full_range()),
127  faderange_(spec.fade_range()),
128  check_fogged_(spec.check_fogged()),
129  check_shrouded_(spec.check_shrouded()),
130  files_(spec.files()),
131  locations_(spec.get_locations())
132 {
133  assert(range_ > 0);
134  assert(faderange_ > 0);
135 }
136 
138 {
140 }
141 
143 {
144  return locations_.empty();
145 }
146 
147 void positional_source::update(unsigned int time, const display &disp)
148 {
149  if (time - last_played_ < unsigned(min_delay_) || sound::is_sound_playing(id_))
150  return;
151 
152  int i = rand() % 100 + 1;
153 
154  if(i <= chance_) {
155  last_played_ = time;
156 
157  // If no locations have been specified, treat the source as if
158  // it was present everywhere on the map
159  if(locations_.empty()) {
160  sound::play_sound_positioned(files_, id_, loops_, 0); // max volume
161  return;
162  }
163 
164  int distance_volume = DISTANCE_SILENT;
165  for(std::vector<map_location>::iterator i = locations_.begin(); i != locations_.end(); ++i) {
166  int v = calculate_volume(*i, disp);
167  if(v < distance_volume) {
168  distance_volume = v;
169  }
170  }
171 
172  if(distance_volume >= DISTANCE_SILENT)
173  return;
174 
175  sound::play_sound_positioned(files_, id_, loops_, distance_volume);
176  }
177 }
178 
179 void positional_source::update_positions(unsigned int time, const display &disp)
180 {
181  if(is_global()) {
182  return;
183  }
184 
185  int distance_volume = DISTANCE_SILENT;
186  for(std::vector<map_location>::iterator i = locations_.begin(); i != locations_.end(); ++i) {
187  int v = calculate_volume(*i, disp);
188  if(v < distance_volume) {
189  distance_volume = v;
190  }
191  }
192 
194  sound::reposition_sound(id_, distance_volume);
195  } else {
196  update(time, disp);
197  }
198 }
199 
201 {
202  assert(range_ > 0);
203  assert(faderange_ > 0);
204 
205  if((check_shrouded_ && disp.shrouded(loc)) || (check_fogged_ && disp.fogged(loc)))
206  return DISTANCE_SILENT;
207 
208  SDL_Rect area = disp.map_area();
209  map_location center = disp.hex_clicked_on(area.x + area.w / 2, area.y + area.h / 2);
210  int distance = distance_between(loc, center);
211 
212  if(distance <= range_) {
213  return 0;
214  }
215 
216  return static_cast<int>((((distance - range_)
217  / static_cast<double>(faderange_)) * DISTANCE_SILENT));
218 }
219 
221 {
222  cfg["sounds"] = files_;
223  cfg["delay"] = min_delay_;
224  cfg["chance"] = chance_;
225  cfg["check_fogged"] = check_fogged_;
226  cfg["check_shrouded"] = check_shrouded_;
227  cfg["loop"] = loops_;
228  cfg["full_range"] = range_;
229  cfg["fade_range"] = faderange_;
231 }
232 
234  id_(cfg["id"]),
235  files_(cfg["sounds"]),
236  min_delay_(cfg["delay"].to_int(DEFAULT_DELAY)),
237  chance_(cfg["chance"].to_int(DEFAULT_CHANCE)),
238  loops_(cfg["loop"]),
239  range_(cfg["full_range"].to_int(3)),
240  faderange_(cfg["fade_range"].to_int(14)),
241  check_fogged_(cfg["check_fogged"].to_bool(true)),
242  check_shrouded_(cfg["check_shrouded"].to_bool(true)),
243  locations_()
244 {
246 }
247 
248 } // namespace soundsource
249 
int calculate_volume(const map_location &loc, const display &disp)
void read_locations(const config &cfg, std::vector< map_location > &locs)
Parse x,y keys of a config into a vector of locations.
Definition: location.cpp:413
bool fogged(const map_location &loc) const
Returns true if location (x,y) is covered in fog.
Definition: display.hpp:353
bool is_sound_playing(int id)
Definition: sound.cpp:678
void play_sound_positioned(const std::string &files, int id, int repeats, unsigned int distance)
Definition: sound.cpp:689
std::string id_
Definition: formula.cpp:636
const map_location hex_clicked_on(int x, int y) const
given x,y co-ordinates of an onscreen pixel, will return the location of the hex that this pixel corr...
Definition: display.cpp:577
void remove(const std::string &id)
Definition: soundsource.cpp:79
events::generic_event & scroll_event() const
Expose the event, so observers can be notified about map scrolling.
Definition: display.hpp:589
const std::string & id() const
void reposition_sound(int id, unsigned int distance)
Definition: sound.cpp:654
positional_source_map::iterator positional_source_iterator
Definition: soundsource.hpp:80
void update(unsigned int time, const display &disp)
void handle_generic_event(const std::string &event_name)
Definition: soundsource.cpp:51
std::vector< map_location > locations_
positional_source_map sources_
Definition: soundsource.hpp:83
size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition: location.hpp:357
const GLdouble * v
Definition: glew.h:1359
void write_config(config &cfg) const
Serializes attributes as WML config.
config & add_child(const std::string &key)
Definition: config.cpp:743
map_display and display: classes which take care of displaying the map and game-data on the screen...
void update_positions(unsigned int time, const display &disp)
Encapsulates the map of the game.
Definition: location.hpp:38
std::vector< map_location > locations_
Definition: soundsource.hpp:46
Sound source info class.
virtual bool attach_handler(observer *obs)
void add(const sourcespec &source)
Definition: soundsource.cpp:57
const unsigned DEFAULT_CHANCE
Definition: soundsource.cpp:28
bool shrouded(const map_location &loc) const
Returns true if location (x,y) is covered in shroud.
Definition: display.hpp:349
positional_source(const sourcespec &spec)
size_t i
Definition: function.cpp:1057
sourcespec(const std::string &id, const std::string &files, int min_delay, int chance)
Parameter-list constructor.
std::string observer
Definition: game_config.cpp:84
manager(const display &disp)
Definition: soundsource.cpp:33
const SDL_Rect & map_area() const
Returns the area used for the map.
Definition: display.cpp:540
#define DISTANCE_SILENT
Definition: sound.hpp:59
display & disp_
Definition: dialogs.cpp:98
Standard logging facilities (interface).
const display & disp_
Definition: soundsource.hpp:84
const unsigned DEFAULT_DELAY
Definition: soundsource.cpp:29
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
config get(const std::string &id)
Definition: soundsource.cpp:69
GLsizei const GLcharARB ** string
Definition: glew.h:4503
positional_source_map::const_iterator positional_source_const_iterator
Definition: soundsource.hpp:81
static unsigned int last_id
Definition: soundsource.hpp:50
void write_sourcespecs(config &cfg) const
Serializes information into cfg as new children of key "sound_source", appended to existing content...
void write_locations(const std::vector< map_location > &locs, config &cfg)
Write a vector of locations into a config adding keys x=x1,x2,..,xn and y=y1,y2,..,yn.
Definition: location.cpp:425