1 /**
2 * Copyright (c) 2006-2011 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty.  In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 *    claim that you wrote the original software. If you use this software
14 *    in a product, an acknowledgment in the product documentation would be
15 *    appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 *    misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20 
21 #include "Mpg123Decoder.h"
22 
23 #include <common/Exception.h>
24 
25 #include <iostream>
26 
27 namespace love
28 {
29 namespace sound
30 {
31 namespace lullaby
32 {
33 
34 	bool Mpg123Decoder::inited = false;
35 
Mpg123Decoder(Data * data,const std::string & ext,int bufferSize)36 	Mpg123Decoder::Mpg123Decoder(Data * data, const std::string & ext, int bufferSize)
37 		: Decoder(data, ext, bufferSize), handle(0), channels(MPG123_STEREO)
38 	{
39 
40 		data_size = data->getSize();
41 		data_offset = 0;
42 
43 		int ret;
44 
45 		if(!inited)
46 		{
47 			ret = mpg123_init();
48 			if (ret != MPG123_OK)
49 				throw love::Exception("Could not initialize mpg123.");
50 			inited = (ret == MPG123_OK);
51 		}
52 
53 		//Intialize the handle
54 		handle = mpg123_new(NULL, &ret);
55 		if (handle == NULL)
56 			throw love::Exception("Could not create handle.");
57 		ret = mpg123_open_feed(handle);
58 		if (ret != MPG123_OK)
59 			throw love::Exception("Could not open feed.");
60 
61 		ret = feed(16384);
62 
63 		if (ret != MPG123_OK && ret != MPG123_DONE)
64 			throw love::Exception("Could not feed!");
65 	}
66 
~Mpg123Decoder()67 	Mpg123Decoder::~Mpg123Decoder()
68 	{
69 		mpg123_close(handle);
70 
71 	}
72 
accepts(const std::string & ext)73 	bool Mpg123Decoder::accepts(const std::string & ext)
74 	{
75 		static const std::string supported[] = {
76 			"mp3", ""
77 		};
78 
79 		for(int i = 0; !(supported[i].empty()); i++)
80 		{
81 			if(supported[i].compare(ext) == 0)
82 				return true;
83 		}
84 
85 		return false;
86 	}
87 
quit()88 	void Mpg123Decoder::quit()
89 	{
90 		if(inited)
91 			mpg123_exit();
92 	}
93 
clone()94 	love::sound::Decoder * Mpg123Decoder::clone()
95 	{
96 		return new Mpg123Decoder(data, ext, bufferSize);
97 	}
98 
decode()99 	int Mpg123Decoder::decode()
100 	{
101 		int size = 0;
102 		bool done = false;
103 
104 		while(size < bufferSize && !done && !eof)
105 		{
106 			size_t numbytes = 0;
107 
108 			int r = mpg123_read(handle, (unsigned char*) buffer + size, bufferSize - size, &numbytes);
109 
110 			switch(r)
111 			{
112 			case MPG123_NEW_FORMAT:
113 				{
114 					long rate = 0;
115 					int encoding = 0;
116 					int ret = mpg123_getformat(handle, &rate, &channels, &encoding);
117 					if (rate == 0)
118 						rate = sampleRate;
119 					else
120 						sampleRate = rate;
121 					if (channels == 0)
122 						channels = MPG123_STEREO;
123 					if (encoding == 0)
124 						encoding = MPG123_ENC_SIGNED_16;
125 					ret = mpg123_format(handle, rate, channels, encoding);
126 					if (ret != MPG123_OK)
127 						throw love::Exception("Could not set output format.");
128 				}
129 				continue;
130 			case MPG123_NEED_MORE:
131 				{
132 					int v = feed(8192);
133 
134 					switch(v)
135 					{
136 					case MPG123_OK:
137 						continue;
138 					case MPG123_DONE:
139 						if(numbytes == 0)
140 							eof = true;
141 						break;
142 					default:
143 						done = true;
144 					}
145 
146 					continue;
147 				}
148 			case MPG123_OK:
149 				size += numbytes;
150 				continue;
151 			case MPG123_DONE:
152 				// Apparently, mpg123_read does not return MPG123_DONE, but
153 				// let's keep it here anyway.
154 				eof = true;
155 			default:
156 				done = true;
157 				break;
158 			}
159 		}
160 
161 		return size;
162 	}
163 
seek(float s)164 	bool Mpg123Decoder::seek(float s)
165 	{
166 		off_t offset = mpg123_timeframe(handle, s);
167 
168 		if(offset < 0)
169 			return false;
170 
171 		if(mpg123_feedseek(handle, 0, SEEK_SET, &offset) >= 0)
172 		{
173 			data_offset = offset;
174 			eof = false;
175 			return true;
176 		}
177 		else
178 			return false;
179 	}
180 
rewind()181 	bool Mpg123Decoder::rewind()
182 	{
183 		eof = false;
184 		off_t offset;
185 
186 		if(mpg123_feedseek(handle, 0, SEEK_SET, &offset) >= 0)
187 		{
188 			data_offset = offset;
189 			return true;
190 		}
191 		else
192 			return false;
193 	}
194 
isSeekable()195 	bool Mpg123Decoder::isSeekable()
196 	{
197 		return true;
198 	}
199 
getChannels() const200 	int Mpg123Decoder::getChannels() const
201 	{
202 		return channels;
203 	}
204 
getBits() const205 	int Mpg123Decoder::getBits() const
206 	{
207 		return 16;
208 	}
209 
feed(int bytes)210 	int Mpg123Decoder::feed(int bytes)
211 	{
212 		int remaining = data_size - data_offset;
213 
214 		if(remaining <= 0)
215 			return MPG123_DONE;
216 
217 		int feed_bytes = remaining < bytes ? remaining : bytes;
218 
219 		int r = mpg123_feed(handle, (unsigned char*)data->getData() + data_offset, feed_bytes);
220 
221 		if(r == MPG123_OK || r == MPG123_DONE)
222 			data_offset += feed_bytes;
223 
224 		return r;
225 	}
226 
227 } // lullaby
228 } // sound
229 } // love
230