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.
46 /// The loop count of the source.
50 typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator;
52 void AUD_SoftwareDevice::create()
56 m_mixer = new AUD_DefaultMixer(m_specs);
58 pthread_mutexattr_t attr;
59 pthread_mutexattr_init(&attr);
60 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
62 pthread_mutex_init(&m_mutex, &attr);
64 pthread_mutexattr_destroy(&attr);
67 void AUD_SoftwareDevice::destroy()
70 playing(m_playback = false);
74 AUD_SoftwareHandle* handle;
76 // delete all playing sounds
77 while(!m_playingSounds.empty())
79 handle = m_playingSounds.front();
80 m_playingSounds.pop_front();
81 delete handle->reader;
85 // delete all paused sounds
86 while(!m_pausedSounds.empty())
88 handle = m_pausedSounds.front();
89 m_pausedSounds.pop_front();
90 delete handle->reader;
94 pthread_mutex_destroy(&m_mutex);
97 void AUD_SoftwareDevice::mix(data_t* buffer, int length)
102 AUD_SoftwareHandle* sound;
106 std::list<AUD_SoftwareHandle*> stopSounds;
107 std::list<AUD_Buffer*> tempBufs;
109 int samplesize = AUD_SAMPLE_SIZE(m_specs);
112 AUD_HandleIterator it = m_playingSounds.begin();
113 while(it != m_playingSounds.end())
116 // increment the iterator to make sure it's valid,
117 // in case the sound gets deleted after stopping
120 // get the buffer from the source
123 sound->reader->read(len, buf);
125 // in case of looping
126 while(pos + len < length && sound->loopcount)
128 tempbuf = new AUD_Buffer(len * samplesize);
129 memcpy(tempbuf->getBuffer(), buf, len * samplesize);
130 tempBufs.push_back(tempbuf);
131 m_mixer->add(tempbuf->getBuffer(), pos, len, sound->volume);
135 if(sound->loopcount > 0)
138 sound->reader->seek(0);
141 sound->reader->read(len, buf);
143 // prevent endless loop
148 m_mixer->add(buf, pos, len, sound->volume);
151 // in case the end of the sound is reached
157 stopSounds.push_back(sound);
162 m_mixer->superpose(buffer, length, m_volume);
165 while(!stopSounds.empty())
167 sound = stopSounds.front();
168 stopSounds.pop_front();
172 while(!tempBufs.empty())
174 tempbuf = tempBufs.front();
175 tempBufs.pop_front();
183 bool AUD_SoftwareDevice::isValid(AUD_Handle* handle)
185 for(AUD_HandleIterator i = m_playingSounds.begin();
186 i != m_playingSounds.end(); i++)
189 for(AUD_HandleIterator i = m_pausedSounds.begin();
190 i != m_pausedSounds.end(); i++)
196 AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
201 AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep)
203 AUD_IReader* reader = factory->createReader();
206 AUD_THROW(AUD_ERROR_READER);
208 // prepare the reader
209 reader = m_mixer->prepare(reader);
214 AUD_SoftwareHandle* sound = new AUD_SoftwareHandle;
216 sound->reader = reader;
217 sound->volume = 1.0f;
218 sound->loopcount = 0;
221 m_playingSounds.push_back(sound);
224 playing(m_playback = true);
230 bool AUD_SoftwareDevice::pause(AUD_Handle* handle)
236 // only songs that are played can be paused
237 for(AUD_HandleIterator i = m_playingSounds.begin();
238 i != m_playingSounds.end(); i++)
242 m_pausedSounds.push_back(*i);
243 m_playingSounds.erase(i);
244 if(m_playingSounds.empty())
245 playing(m_playback = false);
256 bool AUD_SoftwareDevice::resume(AUD_Handle* handle)
262 // only songs that are paused can be resumed
263 for(AUD_HandleIterator i = m_pausedSounds.begin();
264 i != m_pausedSounds.end(); i++)
268 m_playingSounds.push_back(*i);
269 m_pausedSounds.erase(i);
271 playing(m_playback = true);
282 bool AUD_SoftwareDevice::stop(AUD_Handle* handle)
288 for(AUD_HandleIterator i = m_playingSounds.begin();
289 i != m_playingSounds.end(); i++)
295 m_playingSounds.erase(i);
296 if(m_playingSounds.empty())
297 playing(m_playback = false);
304 for(AUD_HandleIterator i = m_pausedSounds.begin();
305 i != m_pausedSounds.end(); i++)
311 m_pausedSounds.erase(i);
323 bool AUD_SoftwareDevice::getKeep(AUD_Handle* handle)
330 result = ((AUD_SoftwareHandle*)handle)->keep;
337 bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep)
345 ((AUD_SoftwareHandle*)handle)->keep = keep;
354 bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position)
362 AUD_IReader* reader = ((AUD_SoftwareHandle*)handle)->reader;
363 reader->seek((int)(position * reader->getSpecs().rate));
372 float AUD_SoftwareDevice::getPosition(AUD_Handle* handle)
376 float position = 0.0f;
380 AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle;
381 position = h->reader->getPosition() / (float)m_specs.rate;
389 AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle)
391 AUD_Status status = AUD_STATUS_INVALID;
395 for(AUD_HandleIterator i = m_playingSounds.begin();
396 i != m_playingSounds.end(); i++)
400 status = AUD_STATUS_PLAYING;
404 if(status == AUD_STATUS_INVALID)
406 for(AUD_HandleIterator i = m_pausedSounds.begin();
407 i != m_pausedSounds.end(); i++)
411 status = AUD_STATUS_PAUSED;
422 void AUD_SoftwareDevice::lock()
424 pthread_mutex_lock(&m_mutex);
427 void AUD_SoftwareDevice::unlock()
429 pthread_mutex_unlock(&m_mutex);
432 float AUD_SoftwareDevice::getVolume() const
437 void AUD_SoftwareDevice::setVolume(float volume)
442 float AUD_SoftwareDevice::getVolume(AUD_Handle* handle)
445 float result = std::numeric_limits<float>::quiet_NaN();
447 result = ((AUD_SoftwareHandle*)handle)->volume;
452 bool AUD_SoftwareDevice::setVolume(AUD_Handle* handle, float volume)
455 bool result = isValid(handle);
457 ((AUD_SoftwareHandle*)handle)->volume = volume;
462 float AUD_SoftwareDevice::getPitch(AUD_Handle* handle)
464 return std::numeric_limits<float>::quiet_NaN();
467 bool AUD_SoftwareDevice::setPitch(AUD_Handle* handle, float pitch)
472 int AUD_SoftwareDevice::getLoopCount(AUD_Handle* handle)
477 result = ((AUD_SoftwareHandle*)handle)->loopcount;
482 bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count)
485 bool result = isValid(handle);
487 ((AUD_SoftwareHandle*)handle)->loopcount = count;