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