1 // Copyright (C) 2006 Ulf Lorenz
2 // Copyright (C) 2006 Andrea Paternesi
3 // Copyright (C) 2007, 2009, 2014, 2015 Ben Asselstine
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 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Library General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 //  02110-1301, USA.
19 
20 #pragma once
21 #ifndef SND_H
22 #define SND_H
23 
24 #include <map>
25 #include <vector>
26 #include <sigc++/trackable.h>
27 
28 class XML_Helper;
29 namespace Gst{
30 class Message;
31 }
32 
33 //! A helper struct to represent a single item in the sound configuration file.
34 struct MusicItem
35 {
36     // The file where the sound piece can be loaded from
37     Glib::ustring file;
38     // Can it be played in the background?
39     bool background;
40     // If loading this file fails, we can define an alias to load instead.
41     Glib::ustring alias;
42 };
43 
44 
45 //! This class manages sound within the game.
46 /** Snd class
47   *
48   * The purpose of putting the sound code into one class is (besides hiding the
49   * internals and supplying a friendly interface) to put all these ugly ifdefs
50   * in one place (sound can be disabled for fewer dependencies).
51   *
52   * @note: As this becomes too complicated, I throw away the caching stuff.
53   *
54   * Sound and music are treated a bit differently since the mixer calls are others.
55   * However, both are referenced by strings (I think in this case, id's aren't
56   * very readable). There are basically two types of music. Background music
57   * is enabled by enableBackground(). It will always play until disabled again
58   * by looking through the databse of available background music pieces. On top
59   * of that, it is possible to play other music pieces. In this case, the
60   * background music fades out (maybe), the other music fades or pops in
61   * and goes away again with the background music taking its place again
62   * afterwards.
63   */
64 class Snd : public sigc::trackable
65 {
66     public:
67 	// Get Methods
68 
69         //! Returns whether music is enabled
70         bool isMusicEnabled();
71 
72         //! Returns the music volume in the range 0..128
73         int getMusicVolume();
74 
75         //! Get the filename for the given piece.
76         Glib::ustring getFile(Glib::ustring piece);
77 
78 	// Set Methods
79 
80         /** Enables/disables music and sets volume. If the sound is disabled,
81           * subsequent calls to play sounds will be silently ignored.
82           *
83           * @param enable       enable/disable sound
84           * @param volume       set the sound volume in the range from 0 to 128
85           *
86           * @return false for wrong volume data, otherwise true
87           */
88         bool setMusic(bool enable, int volume);
89 
90 
91 	// Methods that operate on class data and modify the class.
92 
93         /** Plays a given music piece.
94           *
95           * The current (background) track will be stopped (faded out) if
96           * neccessary and the new piece will be faded in. Each call to
97           * play should be accompanied by a call to halt(), otherwise the
98           * background music wil not continue.
99           *
100           * @param piece        the identifier(name) of the music track to play.
101           * @param nloops       the amount of time the piece should be played
102           *                     (-1: infinitely often)
103           * @param fade         if set to true, fade out a playing music piece
104           * @return false if any error occurred.
105           */
106         bool play(Glib::ustring piece, int nloops = -1, bool fade = true);
107 
108         void updateVolume();
109 
110         /** Stops the current (event) music. Note that the background music might
111           * continue with playing.
112           *
113           * @param fade         if set to true, fade out a playing piece.
114           *
115           * @return false on error.
116           */
117         bool halt(bool fade = true);
118 
119         /** Enables background music.
120           *
121           * Starts playing background music. Picks a random piece that has
122           * the background tag enabled and starts playing it, then picks the
123           * next etc.
124           */
125         void enableBackground();
126 
127         /** Stops playing of background music
128           *
129           */
130         void disableBackground();
131 
132         //! Activates the next background piece
133         void nextPiece();
134 
135 
136 	// Static Methods
137 
138         //! Singleton getter
139         static Snd* getInstance();
140 
141         //! Explicitly delete the singleton
142         static void deleteInstance();
143 
144     private:
145         //! Constructor.  Initializes the sound and loads the music data
146         Snd();
147 
148         //! Destructor.  Deinitializes sound
149         ~Snd();
150 
151         //! Callback for the music data, see XML_Helper
152         bool loadMusic(Glib::ustring tag, XML_Helper* helper);
153 
154 	// DATA
155 
156         // music is stored here, access by d_musicMap[name]
157         std::map<Glib::ustring, MusicItem*> d_musicMap;
158         std::vector<Glib::ustring> d_bgMap;  // shallow copy of background pieces
159 
160 
161         // how many more times we have to loop an effect.
162         gint32 d_nloops;
163 
164         // if initialization failed, set this to true => no music/sound played
165         bool d_broken;
166 
167         // if set to true, play background music
168         bool d_background;
169 
170         struct Impl;
171         Impl *impl;
172         // callbacks
173 
174         bool on_bus_message(const Glib::RefPtr<Gst::Message> & msg, guint32 source);
175         bool on_effect_fade (double step);
176 
177         // static instanton pointer
178         static Snd* s_instance;
179 };
180 
181 #endif //SND_H
182