1 /*******************************************************************************
2 * Copyright 2015-2016 Juan Francisco Crespo Galán
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *   http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************/
16 
17 #include "fx/PlaybackCategory.h"
18 #include "fx/VolumeSound.h"
19 
20 AUD_NAMESPACE_BEGIN
21 
22 struct HandleData {
23 	unsigned int id;
24 	PlaybackCategory* category;
25 };
26 
PlaybackCategory(std::shared_ptr<IDevice> device)27 PlaybackCategory::PlaybackCategory(std::shared_ptr<IDevice> device) :
28 	m_currentID(0), m_device(device), m_status(STATUS_PLAYING), m_volumeStorage(std::make_shared<VolumeStorage>(1.0f))
29 {
30 }
31 
~PlaybackCategory()32 PlaybackCategory::~PlaybackCategory()
33 {
34 	stop();
35 }
36 
play(std::shared_ptr<ISound> sound)37 std::shared_ptr<IHandle> PlaybackCategory::play(std::shared_ptr<ISound> sound)
38 {
39 	std::shared_ptr<ISound> vs(std::make_shared<VolumeSound>(sound, m_volumeStorage));
40 	m_device->lock();
41 	auto handle = m_device->play(vs);
42 	if(handle == nullptr)
43 		return nullptr;
44 	switch (m_status)
45 	{
46 	case STATUS_PAUSED:
47 		handle->pause();
48 		break;
49 	default:
50 		m_status = STATUS_PLAYING;
51 	};
52 	m_handles[m_currentID] = handle;
53 	HandleData* data = new HandleData;
54 	data->category = this;
55 	data->id = m_currentID;
56 	handle->setStopCallback(cleanHandleCallback, data);
57 	m_device->unlock();
58 
59 	m_currentID++;
60 	return handle;
61 }
62 
resume()63 void PlaybackCategory::resume()
64 {
65 	m_device->lock();
66 	for(auto i = m_handles.begin(); i != m_handles.end();)
67 	{
68 		if(i->second->getStatus() == STATUS_INVALID)
69 			i = m_handles.erase(i);
70 		else
71 		{
72 			i->second->resume();
73 			i++;
74 		}
75 	}
76 	m_device->unlock();
77 	m_status = STATUS_PLAYING;
78 }
79 
pause()80 void PlaybackCategory::pause()
81 {
82 	m_device->lock();
83 	for(auto i = m_handles.begin(); i != m_handles.end();)
84 	{
85 		if(i->second->getStatus() == STATUS_INVALID)
86 			i = m_handles.erase(i);
87 		else
88 		{
89 			i->second->pause();
90 			i++;
91 		}
92 	}
93 	m_device->unlock();
94 	m_status = STATUS_PAUSED;
95 }
96 
getVolume()97 float PlaybackCategory::getVolume()
98 {
99 	return m_volumeStorage->getVolume();
100 }
101 
setVolume(float volume)102 void PlaybackCategory::setVolume(float volume)
103 {
104 	m_volumeStorage->setVolume(volume);
105 }
106 
stop()107 void PlaybackCategory::stop()
108 {
109 	m_device->lock();
110 	for(auto i = m_handles.begin(); i != m_handles.end();)
111 	{
112 		i->second->stop();
113 		if(i->second->getStatus() == STATUS_INVALID)
114 			i = m_handles.erase(i);
115 		else
116 			i++;
117 	}
118 	m_device->unlock();
119 	m_status = STATUS_STOPPED;
120 }
121 
getSharedVolume()122 std::shared_ptr<VolumeStorage> PlaybackCategory::getSharedVolume()
123 {
124 	return m_volumeStorage;
125 }
126 
cleanHandles()127 void PlaybackCategory::cleanHandles()
128 {
129 	for(auto i = m_handles.begin(); i != m_handles.end();)
130 	{
131 		if(i->second->getStatus() == STATUS_INVALID)
132 			i = m_handles.erase(i);
133 		else
134 			i++;
135 	}
136 }
137 
cleanHandleCallback(void * data)138 void PlaybackCategory::cleanHandleCallback(void* data)
139 {
140 	auto dat = reinterpret_cast<HandleData*>(data);
141 	dat->category->m_handles.erase(dat->id);
142 	delete dat;
143 }
144 AUD_NAMESPACE_END
145