Commit eb2f413c authored by Max Kellermann's avatar Max Kellermann

Merge branch 'v0.16.x'

Conflicts: NEWS configure.ac
parents e54748d3 736fd0e2
...@@ -19,7 +19,14 @@ ver 0.17 (2011/??/??) ...@@ -19,7 +19,14 @@ ver 0.17 (2011/??/??)
* cue: show CUE track numbers * cue: show CUE track numbers
ver 0.16.3 (2011/??/??) ver 0.16.4 (2011/??/??)
* fix memory leaks
* decoder:
- ffmpeg: workaround for semantic API change in recent ffmpeg versions
- flac: validate the sample rate when scanning the tag
ver 0.16.3 (2011/06/04)
* fix assertion failure in audio format mask parser * fix assertion failure in audio format mask parser
* fix NULL pointer dereference in playlist parser * fix NULL pointer dereference in playlist parser
* fix playlist files in base music directory * fix playlist files in base music directory
......
...@@ -557,15 +557,16 @@ no|avahi|bonjour) ...@@ -557,15 +557,16 @@ no|avahi|bonjour)
;; ;;
esac esac
enable_avahi=no
enable_bounjour=no
if test x$with_zeroconf != xno; then if test x$with_zeroconf != xno; then
if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then
PKG_CHECK_MODULES([AVAHI], [avahi-client avahi-glib], PKG_CHECK_MODULES([AVAHI], [avahi-client avahi-glib],
[found_avahi=1;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] [enable_avahi=yes;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])]
MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS", MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS")
[found_avahi=0])
fi fi
if test x$found_avahi = x1; then if test x$enable_avahi = xyes; then
with_zeroconf=avahi with_zeroconf=avahi
elif test x$with_zeroconf = xavahi; then elif test x$with_zeroconf = xavahi; then
AC_MSG_ERROR([Avahi support requested but not found]) AC_MSG_ERROR([Avahi support requested but not found])
...@@ -573,13 +574,12 @@ if test x$with_zeroconf != xno; then ...@@ -573,13 +574,12 @@ if test x$with_zeroconf != xno; then
if test x$with_zeroconf = xbonjour || test x$with_zeroconf = xauto; then if test x$with_zeroconf = xbonjour || test x$with_zeroconf = xauto; then
AC_CHECK_HEADER(dns_sd.h, AC_CHECK_HEADER(dns_sd.h,
[found_bonjour=1;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])], [enable_bonjour=yes;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])])
[found_bonjour=0])
AC_CHECK_LIB(dns_sd, DNSServiceRegister, AC_CHECK_LIB(dns_sd, DNSServiceRegister,
MPD_LIBS="$MPD_LIBS -ldns_sd") MPD_LIBS="$MPD_LIBS -ldns_sd")
fi fi
if test x$found_bonjour = x1; then if test x$enable_bonjour = xyes; then
with_zeroconf=bonjour with_zeroconf=bonjour
elif test x$with_zeroconf = xbonjour; then elif test x$with_zeroconf = xbonjour; then
AC_MSG_ERROR([Bonjour support requested but not found]) AC_MSG_ERROR([Bonjour support requested but not found])
......
...@@ -8,12 +8,38 @@ ...@@ -8,12 +8,38 @@
<title>General protocol syntax</title> <title>General protocol syntax</title>
<section> <section>
<title>Requests</title> <title>Protocol overview</title>
<para>
The MPD command protocol exchanges line-based text records
between client and server over TCP. Once the client is
connected to the server, they conduct a conversation until the
client closes the connection. The conversation flow is always
initiated by the client.
</para>
<para> <para>
If arguments contain spaces, they should be surrounded by double quotation The client transmits a command sequence, terminated by the
marks. newline character <constant>\n</constant>. The server will
respond with one or more lines, the last of which will be a
completion code.
</para>
<para>
When the client connects to the server, the server will answer
with the following line:
<synopsis>OK MPD version</synopsis>
where <varname>version</varname> is a version identifier such as
0.12.2. This version identifier is the version of the protocol
spoken, not the real version of the daemon. (There is no way to
retrieve this real version identifier from the connection.)
</para> </para>
</section>
<section>
<title>Requests</title>
<cmdsynopsis> <cmdsynopsis>
<command>COMMAND</command> <command>COMMAND</command>
...@@ -21,6 +47,16 @@ ...@@ -21,6 +47,16 @@
</cmdsynopsis> </cmdsynopsis>
<para> <para>
If arguments contain spaces, they should be surrounded by double
quotation marks.
</para>
<para>
Argument strings are separated from the command and any other
arguments by linear white-space (' ' or '\t').
</para>
<para>
All data between the client and the server is encoded in All data between the client and the server is encoded in
UTF-8. (Note: In UTF-8 all standard ansi characters, 0-127 are UTF-8. (Note: In UTF-8 all standard ansi characters, 0-127 are
the same as a standard ansi encoding. Also, no ansi character the same as a standard ansi encoding. Also, no ansi character
...@@ -38,13 +74,97 @@ ...@@ -38,13 +74,97 @@
<title>Responses</title> <title>Responses</title>
<para> <para>
A command returns <returnvalue>OK</returnvalue> on completion A command returns <returnvalue>OK</returnvalue> on completion or
or <returnvalue>ACK some error</returnvalue> on failure. <returnvalue>ACK some error</returnvalue> on failure. These
These denote the end of command execution. denote the end of command execution.
</para> </para>
</section>
<section> <section>
<title>Failure responses</title>
<para>
The nature of the error can be gleaned from the information
that follows the <returnvalue>ACK</returnvalue>.
<returnvalue>ACK</returnvalue> lines are of the form:
<synopsis>ACK [error@command_listNum] {current_command} message_text\n</synopsis>
These responses are generated by a call to
<function>commandError</function>. They contain four separate
terms. Let's look at each of them:
<itemizedlist>
<listitem>
<para>
<returnvalue>error</returnvalue>: numeric value of one
of the <constant>ACK_ERROR</constant> constants defined
in <filename>ack.h</filename>.
</para>
</listitem>
<listitem>
<para>
<returnvalue>command_listNum</returnvalue>:
offset of the command that caused the error in a <link
linkend="command_lists">Command List</link>.
An error will always cause a command list to terminate
at the command that causes the error.
</para>
</listitem>
<listitem>
<para>
<returnvalue>current_command</returnvalue>:
name of the command, in a <link
linkend="command_lists">Command List</link>,
that was executing when the error occurred.
</para>
</listitem>
<listitem>
<para>
<returnvalue>message_text</returnvalue>:
some (hopefully) informative text that describes the
nature of the error.
</para>
</listitem>
</itemizedlist>
</para>
<example>
<title>foo</title>
<para>
An example might help. Consider the following sequence
sent from the client to the server.
<synopsis>
command_list_begin
volume 86
play 10240
status
command_list_end
</synopsis>
</para>
<para>
The server responds with:
<returnvalue>
ACK [50@1] {play} song doesn't exist: "10240"
</returnvalue>
</para>
<para>
This tells us that the play command, which was the
second in the list (the first or only command is
numbered 0), failed with error 50. The number 50
translates to <constant>ACK_ERROR_NO_EXIST</constant>--the
song doesn't exist. This is reiterated by the message text
which also tells us which song doesn't exist.
</para>
</example>
</section>
</section>
<section id="command_lists">
<title>Command lists</title> <title>Command lists</title>
<para> <para>
......
...@@ -456,7 +456,7 @@ cd mpd-version</programlisting> ...@@ -456,7 +456,7 @@ cd mpd-version</programlisting>
</para> </para>
<para> <para>
To configure a filter, add a To configure a playlist plugin, add a
<varname>playlist_plugin</varname> block to <varname>playlist_plugin</varname> block to
<filename>mpd.conf</filename>: <filename>mpd.conf</filename>:
</para> </para>
......
...@@ -60,8 +60,10 @@ ape_scan_internal(FILE *fp, tag_ape_callback_t callback, void *ctx) ...@@ -60,8 +60,10 @@ ape_scan_internal(FILE *fp, tag_ape_callback_t callback, void *ctx)
assert(remaining > 10); assert(remaining > 10);
char *buffer = g_malloc(remaining); char *buffer = g_malloc(remaining);
if (fread(buffer, 1, remaining, fp) != remaining) if (fread(buffer, 1, remaining, fp) != remaining) {
g_free(buffer);
return false; return false;
}
/* read tags */ /* read tags */
unsigned n = GUINT32_FROM_LE(footer.count); unsigned n = GUINT32_FROM_LE(footer.count);
......
...@@ -372,6 +372,7 @@ config_read_file(const char *file, GError **error_r) ...@@ -372,6 +372,7 @@ config_read_file(const char *file, GError **error_r)
assert(*line != 0); assert(*line != 0);
g_propagate_prefixed_error(error_r, error, g_propagate_prefixed_error(error_r, error,
"line %i: ", count); "line %i: ", count);
fclose(fp);
return false; return false;
} }
...@@ -383,6 +384,7 @@ config_read_file(const char *file, GError **error_r) ...@@ -383,6 +384,7 @@ config_read_file(const char *file, GError **error_r)
g_set_error(error_r, config_quark(), 0, g_set_error(error_r, config_quark(), 0,
"unrecognized parameter in config file at " "unrecognized parameter in config file at "
"line %i: %s\n", count, name); "line %i: %s\n", count, name);
fclose(fp);
return false; return false;
} }
...@@ -392,6 +394,7 @@ config_read_file(const char *file, GError **error_r) ...@@ -392,6 +394,7 @@ config_read_file(const char *file, GError **error_r)
"config parameter \"%s\" is first defined " "config parameter \"%s\" is first defined "
"on line %i and redefined on line %i\n", "on line %i and redefined on line %i\n",
name, param->line, count); name, param->line, count);
fclose(fp);
return false; return false;
} }
...@@ -403,6 +406,7 @@ config_read_file(const char *file, GError **error_r) ...@@ -403,6 +406,7 @@ config_read_file(const char *file, GError **error_r)
if (*line != '{') { if (*line != '{') {
g_set_error(error_r, config_quark(), 0, g_set_error(error_r, config_quark(), 0,
"line %i: '{' expected", count); "line %i: '{' expected", count);
fclose(fp);
return false; return false;
} }
...@@ -411,12 +415,15 @@ config_read_file(const char *file, GError **error_r) ...@@ -411,12 +415,15 @@ config_read_file(const char *file, GError **error_r)
g_set_error(error_r, config_quark(), 0, g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after '{'", "line %i: Unknown tokens after '{'",
count); count);
fclose(fp);
return false; return false;
} }
param = config_read_block(fp, &count, string, error_r); param = config_read_block(fp, &count, string, error_r);
if (param == NULL) if (param == NULL) {
fclose(fp);
return false; return false;
}
} else { } else {
/* a string value */ /* a string value */
...@@ -433,6 +440,7 @@ config_read_file(const char *file, GError **error_r) ...@@ -433,6 +440,7 @@ config_read_file(const char *file, GError **error_r)
g_error_free(error); g_error_free(error);
} }
fclose(fp);
return false; return false;
} }
...@@ -440,6 +448,7 @@ config_read_file(const char *file, GError **error_r) ...@@ -440,6 +448,7 @@ config_read_file(const char *file, GError **error_r)
g_set_error(error_r, config_quark(), 0, g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after value", "line %i: Unknown tokens after value",
count); count);
fclose(fp);
return false; return false;
} }
......
...@@ -180,7 +180,7 @@ db_check(void) ...@@ -180,7 +180,7 @@ db_check(void)
} }
/* Check if we can write to the directory */ /* Check if we can write to the directory */
if (access(dirPath, R_OK | W_OK)) { if (access(dirPath, X_OK | W_OK)) {
g_warning("Can't create db file in \"%s\": %s", g_warning("Can't create db file in \"%s\": %s",
dirPath, strerror(errno)); dirPath, strerror(errno));
g_free(dirPath); g_free(dirPath);
......
...@@ -138,6 +138,33 @@ mpd_ffmpeg_stream_open(struct decoder *decoder, struct input_stream *input) ...@@ -138,6 +138,33 @@ mpd_ffmpeg_stream_open(struct decoder *decoder, struct input_stream *input)
return stream; return stream;
} }
/**
* API compatibility wrapper for av_open_input_stream() and
* avformat_open_input().
*/
static int
mpd_ffmpeg_open_input(AVFormatContext **ic_ptr,
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,101,0)
AVIOContext *pb,
#else
ByteIOContext *pb,
#endif
const char *filename,
AVInputFormat *fmt)
{
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,1,3)
AVFormatContext *context = avformat_alloc_context();
if (context == NULL)
return AVERROR(ENOMEM);
context->pb = pb;
*ic_ptr = context;
return avformat_open_input(ic_ptr, filename, fmt, NULL);
#else
return av_open_input_stream(ic_ptr, pb, filename, fmt, NULL);
#endif
}
static void static void
mpd_ffmpeg_stream_close(struct mpd_ffmpeg_stream *stream) mpd_ffmpeg_stream_close(struct mpd_ffmpeg_stream *stream)
{ {
...@@ -317,9 +344,9 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) ...@@ -317,9 +344,9 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
} }
//ffmpeg works with ours "fileops" helper //ffmpeg works with ours "fileops" helper
AVFormatContext *format_context; AVFormatContext *format_context = NULL;
if (av_open_input_stream(&format_context, stream->io, input->uri, if (mpd_ffmpeg_open_input(&format_context, stream->io, input->uri,
input_format, NULL) != 0) { input_format) != 0) {
g_warning("Open failed\n"); g_warning("Open failed\n");
mpd_ffmpeg_stream_close(stream); mpd_ffmpeg_stream_close(stream);
return; return;
...@@ -441,13 +468,26 @@ static const ffmpeg_tag_map ffmpeg_tag_maps[] = { ...@@ -441,13 +468,26 @@ static const ffmpeg_tag_map ffmpeg_tag_maps[] = {
}; };
static bool static bool
ffmpeg_copy_metadata(struct tag *tag, AVMetadata *m, ffmpeg_copy_metadata(struct tag *tag,
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,1,0)
AVDictionary *m,
#else
AVMetadata *m,
#endif
const ffmpeg_tag_map tag_map) const ffmpeg_tag_map tag_map)
{ {
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,1,0)
AVDictionaryEntry *mt = NULL;
while ((mt = av_dict_get(m, tag_map.name, mt, 0)) != NULL)
tag_add_item(tag, tag_map.type, mt->value);
#else
AVMetadataTag *mt = NULL; AVMetadataTag *mt = NULL;
while ((mt = av_metadata_get(m, tag_map.name, mt, 0)) != NULL) while ((mt = av_metadata_get(m, tag_map.name, mt, 0)) != NULL)
tag_add_item(tag, tag_map.type, mt->value); tag_add_item(tag, tag_map.type, mt->value);
#endif
return mt != NULL; return mt != NULL;
} }
...@@ -463,9 +503,9 @@ ffmpeg_stream_tag(struct input_stream *is) ...@@ -463,9 +503,9 @@ ffmpeg_stream_tag(struct input_stream *is)
if (stream == NULL) if (stream == NULL)
return NULL; return NULL;
AVFormatContext *f; AVFormatContext *f = NULL;
if (av_open_input_stream(&f, stream->io, is->uri, if (mpd_ffmpeg_open_input(&f, stream->io, is->uri,
input_format, NULL) != 0) { input_format) != 0) {
mpd_ffmpeg_stream_close(stream); mpd_ffmpeg_stream_close(stream);
return NULL; return NULL;
} }
......
...@@ -224,6 +224,7 @@ flac_tag_apply_metadata(struct tag *tag, const char *track, ...@@ -224,6 +224,7 @@ flac_tag_apply_metadata(struct tag *tag, const char *track,
break; break;
case FLAC__METADATA_TYPE_STREAMINFO: case FLAC__METADATA_TYPE_STREAMINFO:
if (block->data.stream_info.sample_rate > 0)
tag->time = flac_duration(&block->data.stream_info); tag->time = flac_duration(&block->data.stream_info);
break; break;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#ifndef MPD_FLAC_METADATA_H #ifndef MPD_FLAC_METADATA_H
#define MPD_FLAC_METADATA_H #define MPD_FLAC_METADATA_H
#include <assert.h>
#include <stdbool.h> #include <stdbool.h>
#include <FLAC/metadata.h> #include <FLAC/metadata.h>
...@@ -29,6 +30,8 @@ struct replay_gain_info; ...@@ -29,6 +30,8 @@ struct replay_gain_info;
static inline unsigned static inline unsigned
flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
{ {
assert(stream_info->sample_rate > 0);
return (stream_info->total_samples + stream_info->sample_rate - 1) / return (stream_info->total_samples + stream_info->sample_rate - 1) /
stream_info->sample_rate; stream_info->sample_rate;
} }
......
...@@ -106,12 +106,14 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, ...@@ -106,12 +106,14 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
g_set_error(error, ao_output_quark(), 0, g_set_error(error, ao_output_quark(), 0,
"\"%s\" is not a valid ao driver", "\"%s\" is not a valid ao driver",
value); value);
g_free(ad);
return NULL; return NULL;
} }
if ((ai = ao_driver_info(ad->driver)) == NULL) { if ((ai = ao_driver_info(ad->driver)) == NULL) {
g_set_error(error, ao_output_quark(), 0, g_set_error(error, ao_output_quark(), 0,
"problems getting driver info"); "problems getting driver info");
g_free(ad);
return NULL; return NULL;
} }
...@@ -129,6 +131,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, ...@@ -129,6 +131,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
g_set_error(error, ao_output_quark(), 0, g_set_error(error, ao_output_quark(), 0,
"problems parsing options \"%s\"", "problems parsing options \"%s\"",
options[i]); options[i]);
g_free(ad);
return NULL; return NULL;
} }
......
...@@ -103,6 +103,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, ...@@ -103,6 +103,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
if (encoder_plugin == NULL) { if (encoder_plugin == NULL) {
g_set_error(error, httpd_output_quark(), 0, g_set_error(error, httpd_output_quark(), 0,
"No such encoder: %s", encoder_name); "No such encoder: %s", encoder_name);
g_free(httpd);
return NULL; return NULL;
} }
......
...@@ -79,23 +79,27 @@ recorder_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, ...@@ -79,23 +79,27 @@ recorder_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
if (encoder_plugin == NULL) { if (encoder_plugin == NULL) {
g_set_error(error_r, recorder_output_quark(), 0, g_set_error(error_r, recorder_output_quark(), 0,
"No such encoder: %s", encoder_name); "No such encoder: %s", encoder_name);
return NULL; goto failure;
} }
recorder->path = config_get_block_string(param, "path", NULL); recorder->path = config_get_block_string(param, "path", NULL);
if (recorder->path == NULL) { if (recorder->path == NULL) {
g_set_error(error_r, recorder_output_quark(), 0, g_set_error(error_r, recorder_output_quark(), 0,
"'path' not configured"); "'path' not configured");
return NULL; goto failure;
} }
/* initialize encoder */ /* initialize encoder */
recorder->encoder = encoder_init(encoder_plugin, param, error_r); recorder->encoder = encoder_init(encoder_plugin, param, error_r);
if (recorder->encoder == NULL) if (recorder->encoder == NULL)
return NULL; goto failure;
return recorder; return recorder;
failure:
g_free(recorder);
return NULL;
} }
static void static void
......
...@@ -152,7 +152,7 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -152,7 +152,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
if (port == 0) { if (port == 0) {
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"shout port must be configured"); "shout port must be configured");
return NULL; goto failure;
} }
check_block_param("password"); check_block_param("password");
...@@ -174,21 +174,21 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -174,21 +174,21 @@ my_shout_init_driver(const struct audio_format *audio_format,
"shout quality \"%s\" is not a number in the " "shout quality \"%s\" is not a number in the "
"range -1 to 10, line %i", "range -1 to 10, line %i",
value, param->line); value, param->line);
return NULL; goto failure;
} }
if (config_get_block_string(param, "bitrate", NULL) != NULL) { if (config_get_block_string(param, "bitrate", NULL) != NULL) {
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"quality and bitrate are " "quality and bitrate are "
"both defined"); "both defined");
return NULL; goto failure;
} }
} else { } else {
value = config_get_block_string(param, "bitrate", NULL); value = config_get_block_string(param, "bitrate", NULL);
if (value == NULL) { if (value == NULL) {
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"neither bitrate nor quality defined"); "neither bitrate nor quality defined");
return NULL; goto failure;
} }
sd->bitrate = strtol(value, &test, 10); sd->bitrate = strtol(value, &test, 10);
...@@ -196,7 +196,7 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -196,7 +196,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
if (*test != '\0' || sd->bitrate <= 0) { if (*test != '\0' || sd->bitrate <= 0) {
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"bitrate must be a positive integer"); "bitrate must be a positive integer");
return NULL; goto failure;
} }
} }
...@@ -206,12 +206,12 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -206,12 +206,12 @@ my_shout_init_driver(const struct audio_format *audio_format,
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"couldn't find shout encoder plugin \"%s\"", "couldn't find shout encoder plugin \"%s\"",
encoding); encoding);
return NULL; goto failure;
} }
sd->encoder = encoder_init(encoder_plugin, param, error); sd->encoder = encoder_init(encoder_plugin, param, error);
if (sd->encoder == NULL) if (sd->encoder == NULL)
return NULL; goto failure;
if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0) if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0)
shout_format = SHOUT_FORMAT_MP3; shout_format = SHOUT_FORMAT_MP3;
...@@ -225,7 +225,7 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -225,7 +225,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"you cannot stream \"%s\" to shoutcast, use mp3", "you cannot stream \"%s\" to shoutcast, use mp3",
encoding); encoding);
return NULL; goto failure;
} else if (0 == strcmp(value, "shoutcast")) } else if (0 == strcmp(value, "shoutcast"))
protocol = SHOUT_PROTOCOL_ICY; protocol = SHOUT_PROTOCOL_ICY;
else if (0 == strcmp(value, "icecast1")) else if (0 == strcmp(value, "icecast1"))
...@@ -237,7 +237,7 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -237,7 +237,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
"shout protocol \"%s\" is not \"shoutcast\" or " "shout protocol \"%s\" is not \"shoutcast\" or "
"\"icecast1\"or \"icecast2\"", "\"icecast1\"or \"icecast2\"",
value); value);
return NULL; goto failure;
} }
} else { } else {
protocol = SHOUT_PROTOCOL_HTTP; protocol = SHOUT_PROTOCOL_HTTP;
...@@ -256,7 +256,7 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -256,7 +256,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
shout_set_agent(sd->shout_conn, "MPD") != SHOUTERR_SUCCESS) { shout_set_agent(sd->shout_conn, "MPD") != SHOUTERR_SUCCESS) {
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"%s", shout_get_error(sd->shout_conn)); "%s", shout_get_error(sd->shout_conn));
return NULL; goto failure;
} }
/* optional paramters */ /* optional paramters */
...@@ -267,14 +267,14 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -267,14 +267,14 @@ my_shout_init_driver(const struct audio_format *audio_format,
if (value != NULL && shout_set_genre(sd->shout_conn, value)) { if (value != NULL && shout_set_genre(sd->shout_conn, value)) {
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"%s", shout_get_error(sd->shout_conn)); "%s", shout_get_error(sd->shout_conn));
return NULL; goto failure;
} }
value = config_get_block_string(param, "description", NULL); value = config_get_block_string(param, "description", NULL);
if (value != NULL && shout_set_description(sd->shout_conn, value)) { if (value != NULL && shout_set_description(sd->shout_conn, value)) {
g_set_error(error, shout_output_quark(), 0, g_set_error(error, shout_output_quark(), 0,
"%s", shout_get_error(sd->shout_conn)); "%s", shout_get_error(sd->shout_conn));
return NULL; goto failure;
} }
value = config_get_block_string(param, "url", NULL); value = config_get_block_string(param, "url", NULL);
...@@ -307,6 +307,10 @@ my_shout_init_driver(const struct audio_format *audio_format, ...@@ -307,6 +307,10 @@ my_shout_init_driver(const struct audio_format *audio_format,
} }
return sd; return sd;
failure:
free_shout_data(sd);
return NULL;
} }
static bool static bool
......
...@@ -579,8 +579,10 @@ sticker_load(const char *type, const char *uri) ...@@ -579,8 +579,10 @@ sticker_load(const char *type, const char *uri)
bool success; bool success;
success = sticker_list_values(sticker->table, type, uri); success = sticker_list_values(sticker->table, type, uri);
if (!success) if (!success) {
sticker_free(sticker);
return NULL; return NULL;
}
if (g_hash_table_size(sticker->table) == 0) { if (g_hash_table_size(sticker->table) == 0) {
/* don't return empty sticker objects */ /* don't return empty sticker objects */
......
...@@ -37,30 +37,28 @@ my_log_func(G_GNUC_UNUSED const gchar *log_domain, ...@@ -37,30 +37,28 @@ my_log_func(G_GNUC_UNUSED const gchar *log_domain,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const char *path, *name, *value;
GError *error = NULL;
bool success;
int ret;
if (argc != 3) { if (argc != 3) {
g_printerr("Usage: read_conf FILE SETTING\n"); g_printerr("Usage: read_conf FILE SETTING\n");
return 1; return 1;
} }
path = argv[1]; const char *path = argv[1];
name = argv[2]; const char *name = argv[2];
g_log_set_default_handler(my_log_func, NULL); g_log_set_default_handler(my_log_func, NULL);
config_global_init(); config_global_init();
success = config_read_file(path, &error);
GError *error = NULL;
bool success = config_read_file(path, &error);
if (!success) { if (!success) {
g_printerr("%s:", error->message); g_printerr("%s:", error->message);
g_error_free(error); g_error_free(error);
return 1; return 1;
} }
value = config_get_string(name, NULL); const char *value = config_get_string(name, NULL);
int ret;
if (value != NULL) { if (value != NULL) {
g_print("%s\n", value); g_print("%s\n", value);
ret = 0; ret = 0;
...@@ -70,5 +68,5 @@ int main(int argc, char **argv) ...@@ -70,5 +68,5 @@ int main(int argc, char **argv)
} }
config_global_finish(); config_global_finish();
return 0; return ret;
} }
...@@ -106,7 +106,6 @@ int main(int argc, char **argv) ...@@ -106,7 +106,6 @@ int main(int argc, char **argv)
struct filter *filter; struct filter *filter;
const struct audio_format *out_audio_format; const struct audio_format *out_audio_format;
char buffer[4096]; char buffer[4096];
size_t frame_size;
if (argc < 3 || argc > 4) { if (argc < 3 || argc > 4) {
g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n"); g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n");
...@@ -162,8 +161,6 @@ int main(int argc, char **argv) ...@@ -162,8 +161,6 @@ int main(int argc, char **argv)
g_printerr("audio_format=%s\n", g_printerr("audio_format=%s\n",
audio_format_to_string(out_audio_format, &af_string)); audio_format_to_string(out_audio_format, &af_string));
frame_size = audio_format_frame_size(&audio_format);
/* play */ /* play */
while (true) { while (true) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment