1 ////////////////////////////////////////////////////////////
2 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 //    you must not claim that you wrote the original software.
15 //    If you use this software in a product, an acknowledgment
16 //    in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 //    and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
23 ////////////////////////////////////////////////////////////
24 
25 ////////////////////////////////////////////////////////////
26 // Headers
27 ////////////////////////////////////////////////////////////
28 #include <SFML/Audio/Sound.hpp>
29 #include <SFML/Audio/SoundBuffer.hpp>
30 #include <SFML/Audio/ALCheck.hpp>
31 
32 
33 namespace sf
34 {
35 ////////////////////////////////////////////////////////////
Sound()36 Sound::Sound() :
37 m_buffer(NULL)
38 {
39 }
40 
41 
42 ////////////////////////////////////////////////////////////
Sound(const SoundBuffer & buffer)43 Sound::Sound(const SoundBuffer& buffer) :
44 m_buffer(NULL)
45 {
46     setBuffer(buffer);
47 }
48 
49 
50 ////////////////////////////////////////////////////////////
Sound(const Sound & copy)51 Sound::Sound(const Sound& copy) :
52 SoundSource(copy),
53 m_buffer   (NULL)
54 {
55     if (copy.m_buffer)
56         setBuffer(*copy.m_buffer);
57     setLoop(copy.getLoop());
58 }
59 
60 
61 ////////////////////////////////////////////////////////////
~Sound()62 Sound::~Sound()
63 {
64     stop();
65     if (m_buffer)
66         m_buffer->detachSound(this);
67 }
68 
69 
70 ////////////////////////////////////////////////////////////
play()71 void Sound::play()
72 {
73     alCheck(alSourcePlay(m_source));
74 }
75 
76 
77 ////////////////////////////////////////////////////////////
pause()78 void Sound::pause()
79 {
80     alCheck(alSourcePause(m_source));
81 }
82 
83 
84 ////////////////////////////////////////////////////////////
stop()85 void Sound::stop()
86 {
87     alCheck(alSourceStop(m_source));
88 }
89 
90 
91 ////////////////////////////////////////////////////////////
setBuffer(const SoundBuffer & buffer)92 void Sound::setBuffer(const SoundBuffer& buffer)
93 {
94     // First detach from the previous buffer
95     if (m_buffer)
96     {
97         stop();
98         m_buffer->detachSound(this);
99     }
100 
101     // Assign and use the new buffer
102     m_buffer = &buffer;
103     m_buffer->attachSound(this);
104     alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer));
105 }
106 
107 
108 ////////////////////////////////////////////////////////////
setLoop(bool loop)109 void Sound::setLoop(bool loop)
110 {
111     alCheck(alSourcei(m_source, AL_LOOPING, loop));
112 }
113 
114 
115 ////////////////////////////////////////////////////////////
setPlayingOffset(Time timeOffset)116 void Sound::setPlayingOffset(Time timeOffset)
117 {
118     alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
119 }
120 
121 
122 ////////////////////////////////////////////////////////////
getBuffer() const123 const SoundBuffer* Sound::getBuffer() const
124 {
125     return m_buffer;
126 }
127 
128 
129 ////////////////////////////////////////////////////////////
getLoop() const130 bool Sound::getLoop() const
131 {
132     ALint loop;
133     alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
134 
135     return loop != 0;
136 }
137 
138 
139 ////////////////////////////////////////////////////////////
getPlayingOffset() const140 Time Sound::getPlayingOffset() const
141 {
142     ALfloat secs = 0.f;
143     alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
144 
145     return seconds(secs);
146 }
147 
148 
149 ////////////////////////////////////////////////////////////
getStatus() const150 Sound::Status Sound::getStatus() const
151 {
152     return SoundSource::getStatus();
153 }
154 
155 
156 ////////////////////////////////////////////////////////////
operator =(const Sound & right)157 Sound& Sound::operator =(const Sound& right)
158 {
159     // Here we don't use the copy-and-swap idiom, because it would mess up
160     // the list of sound instances contained in the buffers and unnecessarily
161     // destroy/create OpenAL sound sources
162 
163     // Delegate to base class, which copies all the sound attributes
164     SoundSource::operator=(right);
165 
166     // Detach the sound instance from the previous buffer (if any)
167     if (m_buffer)
168     {
169         stop();
170         m_buffer->detachSound(this);
171         m_buffer = NULL;
172     }
173 
174     // Copy the remaining sound attributes
175     if (right.m_buffer)
176         setBuffer(*right.m_buffer);
177     setLoop(right.getLoop());
178 
179     return *this;
180 }
181 
182 
183 ////////////////////////////////////////////////////////////
resetBuffer()184 void Sound::resetBuffer()
185 {
186     // First stop the sound in case it is playing
187     stop();
188 
189     // Detach the buffer
190     if (m_buffer)
191     {
192         alCheck(alSourcei(m_source, AL_BUFFER, 0));
193         m_buffer->detachSound(this);
194         m_buffer = NULL;
195     }
196 }
197 
198 } // namespace sf
199