Mercurial > audlegacy-plugins
comparison src/alac/plugin.c @ 3146:87b0c47089e5
alac: Various patches from Hans de Goede. (Closes #61)
author | William Pitcock <nenolod@atheme.org> |
---|---|
date | Sat, 09 May 2009 13:47:30 -0500 |
parents | 3134a0987162 |
children | d7eea4d29d4a |
comparison
equal
deleted
inserted
replaced
3145:76f5bcf547d5 | 3146:87b0c47089e5 |
---|---|
54 | 54 |
55 static int input_opened = 0; | 55 static int input_opened = 0; |
56 | 56 |
57 gpointer decode_thread(void *args); | 57 gpointer decode_thread(void *args); |
58 static GThread *playback_thread; | 58 static GThread *playback_thread; |
59 static int going = 0; | |
60 static int seek_to = -1; | 59 static int seek_to = -1; |
61 | 60 |
62 extern void set_endian(); | 61 extern void set_endian(); |
63 | 62 |
64 static void alac_about(void) | 63 static void alac_about(void) |
99 } | 98 } |
100 | 99 |
101 stream_destroy(input_stream); | 100 stream_destroy(input_stream); |
102 | 101 |
103 return TRUE; | 102 return TRUE; |
103 } | |
104 | |
105 static int get_duration(demux_res_t *demux_res) | |
106 { | |
107 int i; | |
108 long long samples = 0; | |
109 | |
110 for (i = 0; i < demux_res->num_time_to_samples; i++) | |
111 samples += demux_res->time_to_sample[i].sample_count * | |
112 demux_res->time_to_sample[i].sample_duration; | |
113 | |
114 return (samples * 1000) / demux_res->sample_rate; | |
104 } | 115 } |
105 | 116 |
106 Tuple *build_aud_tuple_from_demux(demux_res_t *demux_res, char *path) | 117 Tuple *build_aud_tuple_from_demux(demux_res_t *demux_res, char *path) |
107 { | 118 { |
108 Tuple *ti = aud_tuple_new_from_filename(path); | 119 Tuple *ti = aud_tuple_new_from_filename(path); |
120 if (demux_res->tuple.day != NULL) | 131 if (demux_res->tuple.day != NULL) |
121 aud_tuple_associate_int(ti, FIELD_YEAR, NULL, atoi(demux_res->tuple.day)); | 132 aud_tuple_associate_int(ti, FIELD_YEAR, NULL, atoi(demux_res->tuple.day)); |
122 | 133 |
123 aud_tuple_associate_string(ti, FIELD_CODEC, NULL, "Apple Lossless (ALAC)"); | 134 aud_tuple_associate_string(ti, FIELD_CODEC, NULL, "Apple Lossless (ALAC)"); |
124 aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossless"); | 135 aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossless"); |
136 aud_tuple_associate_int(ti, FIELD_LENGTH, NULL, get_duration(demux_res)); | |
125 | 137 |
126 return ti; | 138 return ti; |
127 } | 139 } |
128 | 140 |
129 Tuple *build_tuple(char *filename) | 141 Tuple *build_tuple(char *filename) |
161 static InputPlayback *playback; | 173 static InputPlayback *playback; |
162 | 174 |
163 static void play_file(InputPlayback *data) | 175 static void play_file(InputPlayback *data) |
164 { | 176 { |
165 char *filename = data->filename; | 177 char *filename = data->filename; |
166 going = 1; | |
167 playback = data; | 178 playback = data; |
179 playback->playing = TRUE; | |
168 playback_thread = g_thread_self(); | 180 playback_thread = g_thread_self(); |
169 playback->set_pb_ready(playback); | 181 playback->set_pb_ready(playback); |
170 decode_thread(filename); | 182 decode_thread(filename); |
171 } | 183 } |
172 | 184 |
173 static void stop(InputPlayback * data) | 185 static void stop(InputPlayback * data) |
174 { | 186 { |
175 going = 0; | 187 playback->playing = FALSE; |
176 g_thread_join(playback_thread); | 188 g_thread_join(playback_thread); |
177 data->output->close_audio(); | 189 data->output->close_audio(); |
178 } | 190 } |
179 | 191 |
180 static void do_pause(InputPlayback *data, short paused) | 192 static void do_pause(InputPlayback *data, short paused) |
183 } | 195 } |
184 | 196 |
185 static void seek(InputPlayback * data, gint time) | 197 static void seek(InputPlayback * data, gint time) |
186 { | 198 { |
187 seek_to = time; | 199 seek_to = time; |
188 } | |
189 | |
190 static int get_sample_info(demux_res_t *demux_res, uint32_t samplenum, | |
191 uint32_t *sample_duration, | |
192 uint32_t *sample_byte_size) | |
193 { | |
194 unsigned int duration_index_accum = 0; | |
195 unsigned int duration_cur_index = 0; | |
196 | |
197 if (samplenum >= demux_res->num_sample_byte_sizes) | |
198 return 0; | |
199 | |
200 if (!demux_res->num_time_to_samples) | |
201 return 0; | |
202 | |
203 while ((demux_res->time_to_sample[duration_cur_index].sample_count + duration_index_accum) | |
204 <= samplenum) | |
205 { | |
206 duration_index_accum += demux_res->time_to_sample[duration_cur_index].sample_count; | |
207 duration_cur_index++; | |
208 | |
209 if (duration_cur_index >= demux_res->num_time_to_samples) | |
210 return 0; | |
211 } | |
212 | |
213 *sample_duration = demux_res->time_to_sample[duration_cur_index].sample_duration; | |
214 *sample_byte_size = demux_res->sample_byte_size[samplenum]; | |
215 | |
216 return 1; | |
217 } | 200 } |
218 | 201 |
219 void GetBuffer(demux_res_t *demux_res) | 202 void GetBuffer(demux_res_t *demux_res) |
220 { | 203 { |
221 unsigned long destBufferSize = 1024*16; /* 16kb buffer = 4096 frames = 1 alac sample */ | 204 unsigned long destBufferSize = 1024*16; /* 16kb buffer = 4096 frames = 1 alac sample */ |
227 | 210 |
228 unsigned int i; | 211 unsigned int i; |
229 | 212 |
230 buffer = malloc(buffer_size); | 213 buffer = malloc(buffer_size); |
231 | 214 |
232 for (i = 0; i < demux_res->num_sample_byte_sizes && going == 1; i++) | 215 for (i = 0; i < demux_res->num_sample_byte_sizes && playback->playing; i++) |
233 { | 216 { |
234 uint32_t sample_duration; | |
235 uint32_t sample_byte_size; | 217 uint32_t sample_byte_size; |
236 | 218 |
237 int outputBytes; | 219 int outputBytes; |
238 | 220 |
239 #if 0 | 221 #if 0 |
251 seek_to = -1; | 233 seek_to = -1; |
252 } | 234 } |
253 #endif | 235 #endif |
254 | 236 |
255 /* just get one sample for now */ | 237 /* just get one sample for now */ |
256 if (!get_sample_info(demux_res, i, | 238 sample_byte_size = demux_res->sample_byte_size[i]; |
257 &sample_duration, &sample_byte_size)) | |
258 return; | |
259 | 239 |
260 if (buffer_size < sample_byte_size) | 240 if (buffer_size < sample_byte_size) |
261 return; | 241 return; |
262 | 242 |
263 stream_read(demux_res->stream, sample_byte_size, buffer); | 243 stream_read(demux_res->stream, sample_byte_size, buffer); |
267 decode_frame(demux_res->alac, buffer, pDestBuffer, &outputBytes); | 247 decode_frame(demux_res->alac, buffer, pDestBuffer, &outputBytes); |
268 | 248 |
269 /* write */ | 249 /* write */ |
270 bytes_read += outputBytes; | 250 bytes_read += outputBytes; |
271 | 251 |
272 playback->pass_audio(playback, FMT_S16_LE, demux_res->num_channels, outputBytes, pDestBuffer, &going); | 252 playback->pass_audio(playback, FMT_S16_LE, demux_res->num_channels, outputBytes, pDestBuffer, &playback->playing); |
273 } | 253 } |
274 | 254 |
275 free(buffer); | 255 free(buffer); |
276 free(pDestBuffer); | 256 free(pDestBuffer); |
277 } | 257 } |
295 DECLARE_PLUGIN(alac, NULL, NULL, alac_iplist, NULL, NULL, NULL, NULL, NULL); | 275 DECLARE_PLUGIN(alac, NULL, NULL, alac_iplist, NULL, NULL, NULL, NULL, NULL); |
296 | 276 |
297 gpointer decode_thread(void *args) | 277 gpointer decode_thread(void *args) |
298 { | 278 { |
299 demux_res_t demux_res; | 279 demux_res_t demux_res; |
300 gulong duration = 0; /* samples added up */ | |
301 VFSFile *input_file; | 280 VFSFile *input_file; |
302 stream_t *input_stream; | 281 stream_t *input_stream; |
303 Tuple *ti; | 282 Tuple *ti; |
304 gchar *title; | 283 gchar *title; |
305 | 284 |
326 | 305 |
327 /* initialise the sound converter */ | 306 /* initialise the sound converter */ |
328 demux_res.alac = create_alac(demux_res.sample_size, demux_res.num_channels); | 307 demux_res.alac = create_alac(demux_res.sample_size, demux_res.num_channels); |
329 alac_set_info(demux_res.alac, demux_res.codecdata); | 308 alac_set_info(demux_res.alac, demux_res.codecdata); |
330 | 309 |
331 /* Sample rates are multiples of 251?! Apple is *fucking* *insane*! -nenolod */ | |
332 duration = (demux_res.num_sample_byte_sizes * (float)((1024 * demux_res.sample_size) - 1.0) / | |
333 (float)(demux_res.sample_rate / 251)); | |
334 | |
335 playback->output->open_audio(FMT_S16_LE, demux_res.sample_rate, demux_res.num_channels); | 310 playback->output->open_audio(FMT_S16_LE, demux_res.sample_rate, demux_res.num_channels); |
336 playback->set_params(playback, title, duration, -1, demux_res.sample_rate, demux_res.num_channels); | 311 playback->set_params(playback, title, get_duration(&demux_res), -1, demux_res.sample_rate, demux_res.num_channels); |
337 | 312 |
338 /* will convert the entire buffer */ | 313 /* will convert the entire buffer */ |
339 GetBuffer(&demux_res); | 314 GetBuffer(&demux_res); |
340 | 315 |
341 going = 0; | 316 if (playback->playing) { |
317 playback->output->buffer_free(); | |
318 playback->output->buffer_free(); | |
319 while (playback->output->buffer_playing() && playback->playing) | |
320 g_usleep(100000); | |
321 } | |
342 | 322 |
343 stream_destroy(input_stream); | 323 stream_destroy(input_stream); |
344 | 324 |
345 if (input_opened) | 325 if (input_opened) |
346 aud_vfs_fclose(input_file); | 326 aud_vfs_fclose(input_file); |
347 | 327 |
348 playback->output->close_audio(); | 328 playback->output->close_audio(); |
349 | 329 |
330 playback->playing = FALSE; | |
331 | |
350 return NULL; | 332 return NULL; |
351 } | 333 } |