Mpg123DecoderPlugin.cxx 7.84 KB
Newer Older
1
/*
2
 * Copyright 2003-2016 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

20
#include "config.h" /* must be first for large file support */
21
#include "Mpg123DecoderPlugin.hxx"
22
#include "../DecoderAPI.hxx"
23
#include "CheckAudioFormat.hxx"
24
#include "tag/TagHandler.hxx"
25 26 27
#include "tag/TagBuilder.hxx"
#include "tag/ReplayGain.hxx"
#include "tag/MixRamp.hxx"
28
#include "fs/Path.hxx"
29
#include "util/Error.hxx"
30
#include "util/Domain.hxx"
31
#include "util/StringView.hxx"
32
#include "Log.hxx"
33 34

#include <mpg123.h>
35

36
#include <stdio.h>
37

38
static constexpr Domain mpg123_domain("mpg123");
39 40

static bool
41
mpd_mpg123_init(gcc_unused const ConfigBlock &block)
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
{
	mpg123_init();

	return true;
}

static void
mpd_mpg123_finish(void)
{
	mpg123_exit();
}

/**
 * Opens a file with an existing #mpg123_handle.
 *
 * @param handle a handle which was created before; on error, this
 * function will not free it
 * @param audio_format this parameter is filled after successful
 * return
 * @return true on success
 */
static bool
mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
65
		AudioFormat &audio_format)
66 67
{
	/* mpg123_open() wants a writable string :-( */
68
	char *const path2 = const_cast<char *>(path_fs);
69

70
	int error = mpg123_open(handle, path2);
71
	if (error != MPG123_OK) {
72 73 74
		FormatWarning(mpg123_domain,
			      "libmpg123 failed to open %s: %s",
			      path_fs, mpg123_plain_strerror(error));
75 76 77 78 79
		return false;
	}

	/* obtain the audio format */

80 81
	long rate;
	int channels, encoding;
82 83
	error = mpg123_getformat(handle, &rate, &channels, &encoding);
	if (error != MPG123_OK) {
84 85 86
		FormatWarning(mpg123_domain,
			      "mpg123_getformat() failed: %s",
			      mpg123_plain_strerror(error));
87 88 89 90 91
		return false;
	}

	if (encoding != MPG123_ENC_SIGNED_16) {
		/* other formats not yet implemented */
92 93 94
		FormatWarning(mpg123_domain,
			      "expected MPG123_ENC_SIGNED_16, got %d",
			      encoding);
95 96 97
		return false;
	}

98
	Error error2;
99
	if (!audio_format_init_checked(audio_format, rate, SampleFormat::S16,
100
				       channels, error2)) {
101
		LogError(error2);
102 103 104 105 106 107
		return false;
	}

	return true;
}

108 109 110 111 112 113 114
static void
AddTagItem(TagBuilder &tag, TagType type, const mpg123_string &s)
{
	assert(s.p != nullptr);
	assert(s.size >= s.fill);
	assert(s.fill > 0);

115
	tag.AddItem(type, {s.p, s.fill - 1});
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
}

static void
AddTagItem(TagBuilder &tag, TagType type, const mpg123_string *s)
{
	if (s != nullptr)
		AddTagItem(tag, type, *s);
}

static void
mpd_mpg123_id3v2_tag(Decoder &decoder, const mpg123_id3v2 &id3v2)
{
	TagBuilder tag;

	AddTagItem(tag, TAG_TITLE, id3v2.title);
	AddTagItem(tag, TAG_ARTIST, id3v2.artist);
	AddTagItem(tag, TAG_ALBUM, id3v2.album);
	AddTagItem(tag, TAG_DATE, id3v2.year);
	AddTagItem(tag, TAG_GENRE, id3v2.genre);

	for (size_t i = 0, n = id3v2.comments; i < n; ++i)
		AddTagItem(tag, TAG_COMMENT, id3v2.comment_list[i].text);

	decoder_tag(decoder, nullptr, tag.Commit());
}

static void
mpd_mpg123_id3v2_extras(Decoder &decoder, const mpg123_id3v2 &id3v2)
{
	ReplayGainInfo replay_gain;
	replay_gain.Clear();

	MixRampInfo mix_ramp;

	bool found_replay_gain = false, found_mixramp = false;

	for (size_t i = 0, n = id3v2.extras; i < n; ++i) {
		if (ParseReplayGainTag(replay_gain,
				       id3v2.extra[i].description.p,
				       id3v2.extra[i].text.p))
			found_replay_gain = true;
		else if (ParseMixRampTag(mix_ramp,
					 id3v2.extra[i].description.p,
					 id3v2.extra[i].text.p))
			found_mixramp = true;
	}

	if (found_replay_gain)
		decoder_replay_gain(decoder, &replay_gain);

	if (found_mixramp)
		decoder_mixramp(decoder, std::move(mix_ramp));
}

static void
mpd_mpg123_id3v2(Decoder &decoder, const mpg123_id3v2 &id3v2)
{
	mpd_mpg123_id3v2_tag(decoder, id3v2);
	mpd_mpg123_id3v2_extras(decoder, id3v2);
}

static void
mpd_mpg123_meta(Decoder &decoder, mpg123_handle *const handle)
{
	if ((mpg123_meta_check(handle) & MPG123_NEW_ID3) == 0)
		return;

	mpg123_id3v1 *v1;
	mpg123_id3v2 *v2;
	if (mpg123_id3(handle, &v1, &v2) != MPG123_OK)
		return;

	if (v2 != nullptr)
		mpd_mpg123_id3v2(decoder, *v2);
}

192
static void
193
mpd_mpg123_file_decode(Decoder &decoder, Path path_fs)
194 195 196
{
	/* open the file */

197 198
	int error;
	mpg123_handle *const handle = mpg123_new(nullptr, &error);
199
	if (handle == nullptr) {
200 201 202
		FormatError(mpg123_domain,
			    "mpg123_new() failed: %s",
			    mpg123_plain_strerror(error));
203 204 205
		return;
	}

206
	AudioFormat audio_format;
207
	if (!mpd_mpg123_open(handle, path_fs.c_str(), audio_format)) {
208 209 210 211
		mpg123_delete(handle);
		return;
	}

212
	const off_t num_samples = mpg123_length(handle);
213 214 215

	/* tell MPD core we're ready */

216 217 218 219 220
	const auto duration =
		SongTime::FromScale<uint64_t>(num_samples,
					      audio_format.sample_rate);

	decoder_initialized(decoder, audio_format, true, duration);
221

222
	struct mpg123_frameinfo info;
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
	if (mpg123_info(handle, &info) != MPG123_OK) {
		info.vbr = MPG123_CBR;
		info.bitrate = 0;
	}

	switch (info.vbr) {
	case MPG123_ABR:
		info.bitrate = info.abr_rate;
		break;
	case MPG123_CBR:
		break;
	default:
		info.bitrate = 0;
	}

238
	/* the decoder main loop */
239
	DecoderCommand cmd;
240
	do {
241 242 243
		/* read metadata */
		mpd_mpg123_meta(decoder, handle);

244 245
		/* decode */

246 247
		unsigned char buffer[8192];
		size_t nbytes;
248 249 250
		error = mpg123_read(handle, buffer, sizeof(buffer), &nbytes);
		if (error != MPG123_OK) {
			if (error != MPG123_DONE)
251 252 253
				FormatWarning(mpg123_domain,
					      "mpg123_read() failed: %s",
					      mpg123_plain_strerror(error));
254 255 256
			break;
		}

257 258 259 260 261 262 263 264
		/* update bitrate for ABR/VBR */
		if (info.vbr != MPG123_CBR) {
			/* FIXME: maybe skip, as too expensive? */
			/* FIXME: maybe, (info.vbr == MPG123_VBR) ? */
			if (mpg123_info (handle, &info) != MPG123_OK)
				info.bitrate = 0;
		}

265 266
		/* send to MPD */

267
		cmd = decoder_data(decoder, nullptr, buffer, nbytes, info.bitrate);
268

269
		if (cmd == DecoderCommand::SEEK) {
270
			off_t c = decoder_seek_where_frame(decoder);
271 272 273 274 275 276 277 278
			c = mpg123_seek(handle, c, SEEK_SET);
			if (c < 0)
				decoder_seek_error(decoder);
			else {
				decoder_command_finished(decoder);
				decoder_timestamp(decoder, c/(double)audio_format.sample_rate);
			}

279
			cmd = DecoderCommand::NONE;
280
		}
281
	} while (cmd == DecoderCommand::NONE);
282 283 284 285 286 287

	/* cleanup */

	mpg123_delete(handle);
}

288
static bool
289
mpd_mpg123_scan_file(Path path_fs,
290
		     const TagHandler &handler, void *handler_ctx)
291 292
{
	int error;
293
	mpg123_handle *const handle = mpg123_new(nullptr, &error);
294
	if (handle == nullptr) {
295 296 297
		FormatError(mpg123_domain,
			    "mpg123_new() failed: %s",
			    mpg123_plain_strerror(error));
298
		return false;
299 300
	}

301
	AudioFormat audio_format;
302
	if (!mpd_mpg123_open(handle, path_fs.c_str(), audio_format)) {
303
		mpg123_delete(handle);
304
		return false;
305 306
	}

307
	const off_t num_samples = mpg123_length(handle);
308 309
	if (num_samples <= 0) {
		mpg123_delete(handle);
310
		return false;
311 312 313 314 315
	}

	/* ID3 tag support not yet implemented */

	mpg123_delete(handle);
316

317 318 319 320 321
	const auto duration =
		SongTime::FromScale<uint64_t>(num_samples,
					      audio_format.sample_rate);

	tag_handler_invoke_duration(handler, handler_ctx, duration);
322
	return true;
323 324 325 326
}

static const char *const mpg123_suffixes[] = {
	"mp3",
327
	nullptr
328 329
};

330
const struct DecoderPlugin mpg123_decoder_plugin = {
331 332 333
	"mpg123",
	mpd_mpg123_init,
	mpd_mpg123_finish,
334
	/* streaming not yet implemented */
335 336 337 338 339 340 341
	nullptr,
	mpd_mpg123_file_decode,
	mpd_mpg123_scan_file,
	nullptr,
	nullptr,
	mpg123_suffixes,
	nullptr,
342
};