audio_parser.c 3.89 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 * 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.
14 15 16 17
 *
 * 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.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 */

/*
 * Parser functions for audio related objects.
 *
 */

#include "audio_parser.h"
#include "audio_format.h"

#include <stdlib.h>

/**
 * The GLib quark used for errors reported by this library.
 */
static inline GQuark
audio_parser_quark(void)
{
	return g_quark_from_static_string("audio_parser");
}

39
static bool
40
parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
41
		  const char **endptr_r, GError **error_r)
42 43
{
	unsigned long value;
44
	char *endptr;
45

46 47 48 49 50 51
	if (mask && *src == '*') {
		*sample_rate_r = 0;
		*endptr_r = src + 1;
		return true;
	}

52 53
	value = strtoul(src, &endptr, 10);
	if (endptr == src) {
54
		g_set_error(error_r, audio_parser_quark(), 0,
55
			    "Failed to parse the sample rate");
56
		return false;
57
	} else if (!audio_valid_sample_rate(value)) {
58
		g_set_error(error_r, audio_parser_quark(), 0,
59 60 61 62
			    "Invalid sample rate: %lu", value);
		return false;
	}

63 64 65 66
	*sample_rate_r = value;
	*endptr_r = endptr;
	return true;
}
67

68
static bool
69
parse_sample_format(const char *src, bool mask, uint8_t *bits_r,
70 71 72 73
		    const char **endptr_r, GError **error_r)
{
	unsigned long value;
	char *endptr;
74

75 76 77 78 79 80
	if (mask && *src == '*') {
		*bits_r = 0;
		*endptr_r = src + 1;
		return true;
	}

81 82
	value = strtoul(src, &endptr, 10);
	if (endptr == src) {
83
		g_set_error(error_r, audio_parser_quark(), 0,
84
			    "Failed to parse the sample format");
85
		return false;
86
	} else if (!audio_valid_sample_format(value)) {
87
		g_set_error(error_r, audio_parser_quark(), 0,
88 89 90 91
			    "Invalid sample format: %lu", value);
		return false;
	}

92 93 94 95
	*bits_r = value;
	*endptr_r = endptr;
	return true;
}
96

97
static bool
98
parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
99 100 101 102
		    const char **endptr_r, GError **error_r)
{
	unsigned long value;
	char *endptr;
103

104 105 106 107 108 109
	if (mask && *src == '*') {
		*channels_r = 0;
		*endptr_r = src + 1;
		return true;
	}

110
	value = strtoul(src, &endptr, 10);
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
	if (endptr == src) {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Failed to parse the channel count");
		return false;
	} else if (!audio_valid_channel_count(value)) {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Invalid channel count: %lu", value);
		return false;
	}

	*channels_r = value;
	*endptr_r = endptr;
	return true;
}

bool
audio_format_parse(struct audio_format *dest, const char *src,
128
		   bool mask, GError **error_r)
129 130 131 132 133 134 135 136
{
	uint32_t rate;
	uint8_t bits, channels;

	audio_format_clear(dest);

	/* parse sample rate */

137
	if (!parse_sample_rate(src, mask, &rate, &src, error_r))
138 139 140
		return false;

	if (*src++ != ':') {
141
		g_set_error(error_r, audio_parser_quark(), 0,
142
			    "Sample format missing");
143 144 145
		return false;
	}

146 147
	/* parse sample format */

148
	if (!parse_sample_format(src, mask, &bits, &src, error_r))
149 150 151 152 153 154 155 156 157 158
		return false;

	if (*src++ != ':') {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Channel count missing");
		return false;
	}

	/* parse channel count */

159
	if (!parse_channel_count(src, mask, &channels, &src, error_r))
160 161 162 163 164 165 166
		return false;

	if (*src != 0) {
		g_set_error(error_r, audio_parser_quark(), 0,
			    "Extra data after channel count: %s", src);
		return false;
	}
167 168

	audio_format_init(dest, rate, bits, channels);
169 170 171

	return true;
}