1
/*
2
 * Copyright 2008-2011 Various Authors
3
 * Copyright 2006 Chun-Yu Shei <cshei AT cs.indiana.edu>
4
 *
5
 * Cleaned up by Timo Hirvonen <tihirvon@gmail.com>
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License as
9
 * published by the Free Software Foundation; either version 2 of the
10
 * License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "ip.h"
22
#include "ape.h"
23
#include "comment.h"
24
#include "file.h"
25
#include "xmalloc.h"
26
#include "read_wrapper.h"
27
28
#ifdef HAVE_CONFIG
29
#include "config/mpc.h"
30
#endif
31
32
#if MPC_SV8
33
#include <mpc/mpcdec.h>
34
#define callback_t mpc_reader
35
#define get_ip_data(d) (d)->data
36
#else
37
#include <mpcdec/mpcdec.h>
38
#define MPC_FALSE FALSE
39
#define MPC_TRUE TRUE
40
#define callback_t void
41
#define get_ip_data(d) (d)
42
#endif
43
44
#include <stdint.h>
45
#include <sys/types.h>
46
#include <unistd.h>
47
#include <errno.h>
48
49
struct mpc_private {
50
#if MPC_SV8
51
	mpc_demux *decoder;
52
#else
53
	mpc_decoder decoder;
54
#endif
55
	mpc_reader reader;
56
	mpc_streaminfo info;
57
58
	off_t file_size;
59
60
	int samples_pos;
61
	int samples_avail;
62
63
	/* mpcdec/mpcdec.h
64
	 *
65
	 * the api doc says this is pcm samples per mpc frame
66
	 * but it's really pcm _frames_ per mpc frame
67
	 *     MPC_FRAME_LENGTH = 36 * 32 (1152)
68
	 *
69
	 * this is wrong, it should be 2 * MPC_FRAME_LENGTH (2304)
70
	 *     MPC_DECODER_BUFFER_LENGTH = 4 * MPC_FRAME_LENGTH (4608)
71
	 *
72
	 * use MPC_DECODER_BUFFER_LENGTH just to be sure it works
73
	 */
74
	MPC_SAMPLE_FORMAT samples[MPC_DECODER_BUFFER_LENGTH];
75
76
	struct {
77
		unsigned long samples;
78
		unsigned long bits;
79
	} current;
80
};
81
82
/* callbacks */
83
static mpc_int32_t read_impl(callback_t *data, void *ptr, mpc_int32_t size)
84
{
85
	struct input_plugin_data *ip_data = get_ip_data(data);
86
	int rc;
87
88
	rc = read_wrapper(ip_data, ptr, size);
89
	if (rc == -1)
90
		return -1;
91
	if (rc == 0) {
92
		errno = 0;
93
		return 0;
94
	}
95
	return rc;
96
}
97
98
static mpc_bool_t seek_impl(callback_t *data, mpc_int32_t offset)
99
{
100
	struct input_plugin_data *ip_data = get_ip_data(data);
101
102
	if (lseek(ip_data->fd, offset, SEEK_SET) == -1)
103
		return MPC_FALSE;
104
	return MPC_TRUE;
105
}
106
107
static mpc_int32_t tell_impl(callback_t *data)
108
{
109
	struct input_plugin_data *ip_data = get_ip_data(data);
110
111
	return lseek(ip_data->fd, 0, SEEK_CUR);
112
}
113
114
static mpc_int32_t get_size_impl(callback_t *data)
115
{
116
	struct input_plugin_data *ip_data = get_ip_data(data);
117
	struct mpc_private *priv = ip_data->private;
118
119
	return priv->file_size;
120
}
121
122
static mpc_bool_t canseek_impl(callback_t *data)
123
{
124
	struct input_plugin_data *ip_data = get_ip_data(data);
125
126
	return !ip_data->remote;
127
}
128
129
static int mpc_open(struct input_plugin_data *ip_data)
130
{
131
	struct mpc_private *priv;
132
133
	const struct mpc_private priv_init = {
134
		.file_size = -1,
135
		/* set up an mpc_reader linked to our function implementations */
136
		.reader = {
137
			.read     = read_impl,
138
			.seek     = seek_impl,
139
			.tell     = tell_impl,
140
			.get_size = get_size_impl,
141
			.canseek  = canseek_impl,
142
			.data     = ip_data
143
		}
144
	};
145
146
	priv = xnew(struct mpc_private, 1);
147
	*priv = priv_init;
148
149
	if (!ip_data->remote) {
150
		priv->file_size = lseek(ip_data->fd, 0, SEEK_END);
151
		lseek(ip_data->fd, 0, SEEK_SET);
152
	}
153
154
	/* must be before mpc_streaminfo_read() */
155
	ip_data->private = priv;
156
157
	/* read file's streaminfo data */
158
#if MPC_SV8
159
	priv->decoder = mpc_demux_init(&priv->reader);
160
	if (!priv->decoder) {
161
#else
162
	mpc_streaminfo_init(&priv->info);
163
	if (mpc_streaminfo_read(&priv->info, &priv->reader) != ERROR_CODE_OK) {
164
#endif
165
		free(priv);
166
		return -IP_ERROR_FILE_FORMAT;
167
	}
168
169
#if MPC_SV8
170
	mpc_demux_get_info(priv->decoder, &priv->info);
171
#else
172
	/* instantiate a decoder with our file reader */
173
	mpc_decoder_setup(&priv->decoder, &priv->reader);
174
	if (!mpc_decoder_initialize(&priv->decoder, &priv->info)) {
175
		free(priv);
176
		return -IP_ERROR_FILE_FORMAT;
177
	}
178
#endif
179
180
	priv->samples_avail = 0;
181
	priv->samples_pos = 0;
182
183
	ip_data->sf = sf_rate(priv->info.sample_freq) | sf_channels(priv->info.channels) |
184
		sf_bits(16) | sf_signed(1);
185
	channel_map_init_waveex(priv->info.channels, 0, ip_data->channel_map);
186
	return 0;
187
}
188
189
static int mpc_close(struct input_plugin_data *ip_data)
190
{
191
	struct mpc_private *priv = ip_data->private;
192
193
#if MPC_SV8
194
	mpc_demux_exit(priv->decoder);
195
#endif
196
	free(priv);
197
	ip_data->private = NULL;
198
	return 0;
199
}
200
201
static int scale(struct input_plugin_data *ip_data, char *buffer, int count)
202
{
203
	struct mpc_private *priv = ip_data->private;
204
	const MPC_SAMPLE_FORMAT *samples;
205
	const int clip_min = -1 << (16 - 1);
206
	const int clip_max = (1 << (16 - 1)) - 1;
207
	const int float_scale = 1 << (16 - 1);
208
	int i, sample_count;
209
210
	/* number of bytes to 16-bit samples */
211
	sample_count = count / 2;
212
	if (sample_count > priv->samples_avail)
213
		sample_count = priv->samples_avail;
214
215
	/* scale 32-bit samples to 16-bit */
216
	samples = priv->samples + priv->samples_pos;
217
	for (i = 0; i < sample_count; i++) {
218
		int val;
219
220
		val = samples[i] * float_scale;
221
		if (val < clip_min) {
222
			val = clip_min;
223
		} else if (val > clip_max) {
224
			val = clip_max;
225
		}
226
227
		buffer[i * 2 + 0] = val & 0xff;
228
		buffer[i * 2 + 1] = val >> 8;
229
	}
230
231
	priv->samples_pos += sample_count;
232
	priv->samples_avail -= sample_count;
233
	if (priv->samples_avail == 0)
234
		priv->samples_pos = 0;
235
236
	/* number of 16-bit samples to bytes */
237
	return sample_count * 2;
238
}
239
240
static int mpc_read(struct input_plugin_data *ip_data, char *buffer, int count)
241
{
242
	struct mpc_private *priv = ip_data->private;
243
244
#if MPC_SV8
245
	mpc_status status;
246
	mpc_frame_info frame;
247
	int samples;
248
249
	frame.buffer = priv->samples;
250
251
	while (priv->samples_avail == 0) {
252
		status = mpc_demux_decode(priv->decoder, &frame);
253
254
		if (status != MPC_STATUS_OK) {
255
			return -IP_ERROR_ERRNO;
256
		}
257
		if (frame.bits == -1) {
258
			/* EOF */
259
			return 0;
260
		}
261
262
		samples = frame.samples;
263
		priv->samples_avail = samples * priv->info.channels;
264
265
		priv->current.samples += frame.samples;
266
		priv->current.bits += frame.bits;
267
	}
268
#else
269
270
	if (priv->samples_avail == 0) {
271
		uint32_t acc = 0, bits = 0;
272
		uint32_t status = mpc_decoder_decode(&priv->decoder, priv->samples, &acc, &bits);
273
274
		if (status == (uint32_t)(-1)) {
275
			/* right ret val? */
276
			return -IP_ERROR_ERRNO;
277
		}
278
		if (status == 0) {
279
			/* EOF */
280
			return 0;
281
		}
282
283
		/* status seems to be number of _frames_
284
		 * the api documentation is wrong
285
		 */
286
		priv->samples_avail = status * priv->info.channels;
287
288
		priv->current.samples += status;
289
		priv->current.bits += bits;
290
	}
291
#endif
292
293
	return scale(ip_data, buffer, count);
294
}
295
296
static int mpc_seek(struct input_plugin_data *ip_data, double offset)
297
{
298
	struct mpc_private *priv = ip_data->private;
299
300
	priv->samples_pos = 0;
301
	priv->samples_avail = 0;
302
303
#if MPC_SV8
304
	if (mpc_demux_seek_second(priv->decoder, offset) == MPC_STATUS_OK)
305
#else
306
	if (mpc_decoder_seek_seconds(&priv->decoder, offset))
307
#endif
308
		return 0;
309
	return -1;
310
}
311
312
static const char *gain_to_str(int gain)
313
{
314
	static char buf[16];
315
#if MPC_SV8
316
	float g = MPC_OLD_GAIN_REF - gain / 256.f;
317
	sprintf(buf, "%.2f", g);
318
#else
319
	int b, a = gain / 100;
320
321
	if (gain < 0) {
322
		b = -gain % 100;
323
	} else {
324
		b = gain % 100;
325
	}
326
	sprintf(buf, "%d.%02d", a, b);
327
#endif
328
	return buf;
329
}
330
331
static const char *peak_to_str(unsigned int peak)
332
{
333
	static char buf[16];
334
#if MPC_SV8
335
	sprintf(buf, "%.5f", peak / 256.f / 100.f);
336
#else
337
	sprintf(buf, "%d.%05d", peak / 32767, peak % 32767);
338
#endif
339
	return buf;
340
}
341
342
static int mpc_read_comments(struct input_plugin_data *ip_data, struct keyval **comments)
343
{
344
	struct mpc_private *priv = ip_data->private;
345
	GROWING_KEYVALS(c);
346
	int count, i;
347
	APETAG(ape);
348
349
	count = ape_read_tags(&ape, ip_data->fd, 1);
350
	if (count < 0)
351
		goto out;
352
353
	for (i = 0; i < count; i++) {
354
		char *k, *v;
355
		k = ape_get_comment(&ape, &v);
356
		if (!k)
357
			break;
358
		comments_add(&c, k, v);
359
		free(k);
360
	}
361
362
out:
363
	if (priv->info.gain_title && priv->info.peak_title) {
364
		comments_add_const(&c, "replaygain_track_gain", gain_to_str(priv->info.gain_title));
365
		comments_add_const(&c, "replaygain_track_peak", peak_to_str(priv->info.peak_title));
366
	}
367
	if (priv->info.gain_album && priv->info.peak_album) {
368
		comments_add_const(&c, "replaygain_album_gain", gain_to_str(priv->info.gain_album));
369
		comments_add_const(&c, "replaygain_album_peak", peak_to_str(priv->info.peak_album));
370
	}
371
	keyvals_terminate(&c);
372
373
	*comments = c.keyvals;
374
	ape_free(&ape);
375
	return 0;
376
}
377
378
static int mpc_duration(struct input_plugin_data *ip_data)
379
{
380
	struct mpc_private *priv = ip_data->private;
381
382
	/* priv->info.pcm_samples seems to be number of frames
383
	 * priv->info.frames is _not_ pcm frames
384
	 */
385
#if MPC_SV8
386
	return mpc_streaminfo_get_length(&priv->info);
387
#else
388
	return priv->info.pcm_samples / priv->info.sample_freq;
389
#endif
390
}
391
392
static long mpc_bitrate(struct input_plugin_data *ip_data)
393
{
394
	struct mpc_private *priv = ip_data->private;
395
	if (priv->info.average_bitrate)
396
		return (long) (priv->info.average_bitrate + 0.5);
397
	if (priv->info.bitrate)
398
		return priv->info.bitrate;
399
	return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
400
}
401
402
static long mpc_current_bitrate(struct input_plugin_data *ip_data)
403
{
404
	struct mpc_private *priv = ip_data->private;
405
	long bitrate = -1;
406
	if (priv->current.samples > 0) {
407
		bitrate = (priv->info.sample_freq * priv->current.bits) / priv->current.samples;
408
		priv->current.samples = 0;
409
		priv->current.bits = 0;
410
	}
411
	return bitrate;
412
413
}
414
415
static char *mpc_codec(struct input_plugin_data *ip_data)
416
{
417
	struct mpc_private *priv = ip_data->private;
418
	switch (priv->info.stream_version) {
419
	case 7:
420
		return xstrdup("mpc7");
421
	case 8:
422
		return xstrdup("mpc8");
423
	}
424
	return NULL;
425
}
426
427
static char *mpc_codec_profile(struct input_plugin_data *ip_data)
428
{
429
	struct mpc_private *priv = ip_data->private;
430
	const char *profile = priv->info.profile_name;
431
	char *s = NULL;
432
433
	if (profile && profile[0]) {
434
		int i;
435
436
		/* remove single quotes */
437
		while (*profile == '\'')
438
			profile++;
439
		s = xstrdup(profile);
440
		for (i = strlen(s) - 1; s[i] == '\'' && i >= 0; i--)
441
			s[i] = '\0';
442
	}
443
444
	return s;
445
}
446
447
const struct input_plugin_ops ip_ops = {
448
	.open = mpc_open,
449
	.close = mpc_close,
450
	.read = mpc_read,
451
	.seek = mpc_seek,
452
	.read_comments = mpc_read_comments,
453
	.duration = mpc_duration,
454
	.bitrate = mpc_bitrate,
455
	.bitrate_current = mpc_current_bitrate,
456
	.codec = mpc_codec,
457
	.codec_profile = mpc_codec_profile
458
};
459
460
const int ip_priority = 50;
461
const char *const ip_extensions[] = { "mpc", "mpp", "mp+", NULL };
462
const char *const ip_mime_types[] = { "audio/x-musepack", NULL };
463
const char *const ip_options[] = { NULL };