4 * ***** BEGIN LGPL LICENSE BLOCK *****
6 * Copyright 2009 Jörg Hermann Müller
8 * This file is part of AudaSpace.
10 * AudaSpace is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * AudaSpace is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
23 * ***** END LGPL LICENSE BLOCK *****
26 #include "AUD_SoftwareDevice.h"
27 #include "AUD_IReader.h"
28 #include "AUD_DefaultMixer.h"
29 #include "AUD_IFactory.h"
34 /// Saves the data for playback.
35 struct AUD_SoftwareHandle : AUD_Handle
37 /// The reader source.
40 /// Whether to keep the source if end of it is reached.
43 /// The volume of the source.
47 typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator;
49 void AUD_SoftwareDevice::create()
51 m_playingSounds = new std::list<AUD_SoftwareHandle*>();
52 m_pausedSounds = new std::list<AUD_SoftwareHandle*>();
55 m_mixer = new AUD_DefaultMixer(m_specs);
57 pthread_mutexattr_t attr;
58 pthread_mutexattr_init(&attr);
59 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
61 pthread_mutex_init(&m_mutex, &attr);
63 pthread_mutexattr_destroy(&attr);
66 void AUD_SoftwareDevice::destroy()
69 playing(m_playback = false);
73 // delete all playing sounds
74 while(m_playingSounds->begin() != m_playingSounds->end())
76 delete (*(m_playingSounds->begin()))->reader;
77 delete *(m_playingSounds->begin());
78 m_playingSounds->erase(m_playingSounds->begin());
80 delete m_playingSounds;
82 // delete all paused sounds
83 while(m_pausedSounds->begin() != m_pausedSounds->end())
85 delete (*(m_pausedSounds->begin()))->reader;
86 delete *(m_pausedSounds->begin());
87 m_pausedSounds->erase(m_pausedSounds->begin());
89 delete m_pausedSounds;
91 pthread_mutex_destroy(&m_mutex);
94 void AUD_SoftwareDevice::mix(data_t* buffer, int length)
99 AUD_SoftwareHandle* sound;
102 std::list<AUD_SoftwareHandle*> stopSounds;
105 AUD_HandleIterator it = m_playingSounds->begin();
106 while(it != m_playingSounds->end())
109 // increment the iterator to make sure it's valid,
110 // in case the sound gets deleted after stopping
113 // get the buffer from the source
115 sound->reader->read(len, buf);
117 m_mixer->add(buf, 0, len, sound->volume);
119 // in case the end of the sound is reached
125 stopSounds.push_back(sound);
130 m_mixer->superpose(buffer, length, m_volume);
132 while(!stopSounds.empty())
134 sound = stopSounds.front();
135 stopSounds.pop_front();
143 bool AUD_SoftwareDevice::isValid(AUD_Handle* handle)
145 for(AUD_HandleIterator i = m_playingSounds->begin();
146 i != m_playingSounds->end(); i++)
149 for(AUD_HandleIterator i = m_pausedSounds->begin();
150 i != m_pausedSounds->end(); i++)
156 AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
161 AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep)
163 AUD_IReader* reader = factory->createReader();
166 AUD_THROW(AUD_ERROR_READER);
168 // prepare the reader
169 reader = m_mixer->prepare(reader);
173 AUD_Specs rs = reader->getSpecs();
176 AUD_SoftwareHandle* sound = new AUD_SoftwareHandle;
178 sound->reader = reader;
179 sound->volume = 1.0f;
182 m_playingSounds->push_back(sound);
185 playing(m_playback = true);
191 bool AUD_SoftwareDevice::pause(AUD_Handle* handle)
197 // only songs that are played can be paused
198 for(AUD_HandleIterator i = m_playingSounds->begin();
199 i != m_playingSounds->end(); i++)
203 m_pausedSounds->push_back(*i);
204 m_playingSounds->erase(i);
205 if(m_playingSounds->empty())
206 playing(m_playback = false);
217 bool AUD_SoftwareDevice::resume(AUD_Handle* handle)
223 // only songs that are paused can be resumed
224 for(AUD_HandleIterator i = m_pausedSounds->begin();
225 i != m_pausedSounds->end(); i++)
229 m_playingSounds->push_back(*i);
230 m_pausedSounds->erase(i);
232 playing(m_playback = true);
243 bool AUD_SoftwareDevice::stop(AUD_Handle* handle)
249 for(AUD_HandleIterator i = m_playingSounds->begin();
250 i != m_playingSounds->end(); i++)
256 m_playingSounds->erase(i);
257 if(m_playingSounds->empty())
258 playing(m_playback = false);
265 for(AUD_HandleIterator i = m_pausedSounds->begin();
266 i != m_pausedSounds->end(); i++)
272 m_pausedSounds->erase(i);
284 bool AUD_SoftwareDevice::getKeep(AUD_Handle* handle)
291 result = ((AUD_SoftwareHandle*)handle)->keep;
298 bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep)
306 ((AUD_SoftwareHandle*)handle)->keep = keep;
315 bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position)
323 AUD_IReader* reader = ((AUD_SoftwareHandle*)handle)->reader;
324 reader->seek((int)(position * reader->getSpecs().rate));
333 float AUD_SoftwareDevice::getPosition(AUD_Handle* handle)
337 float position = 0.0f;
341 AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle;
342 position = h->reader->getPosition() / (float)m_specs.rate;
350 AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle)
352 AUD_Status status = AUD_STATUS_INVALID;
356 for(AUD_HandleIterator i = m_playingSounds->begin();
357 i != m_playingSounds->end(); i++)
361 status = AUD_STATUS_PLAYING;
365 if(status == AUD_STATUS_INVALID)
367 for(AUD_HandleIterator i = m_pausedSounds->begin();
368 i != m_pausedSounds->end(); i++)
372 status = AUD_STATUS_PAUSED;
383 void AUD_SoftwareDevice::lock()
385 pthread_mutex_lock(&m_mutex);
388 void AUD_SoftwareDevice::unlock()
390 pthread_mutex_unlock(&m_mutex);
393 float AUD_SoftwareDevice::getVolume() const
398 void AUD_SoftwareDevice::setVolume(float volume)
403 float AUD_SoftwareDevice::getVolume(AUD_Handle* handle)
406 float result = std::numeric_limits<float>::quiet_NaN();
408 result = ((AUD_SoftwareHandle*)handle)->volume;
413 bool AUD_SoftwareDevice::setVolume(AUD_Handle* handle, float volume)
416 bool result = isValid(handle);
418 ((AUD_SoftwareHandle*)handle)->volume = volume;
423 float AUD_SoftwareDevice::getPitch(AUD_Handle* handle)
425 return std::numeric_limits<float>::quiet_NaN();
428 bool AUD_SoftwareDevice::setPitch(AUD_Handle* handle, float pitch)