commit
eb2f413cf0
9
NEWS
9
NEWS
|
@ -19,7 +19,14 @@ ver 0.17 (2011/??/??)
|
|||
* 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 NULL pointer dereference in playlist parser
|
||||
* fix playlist files in base music directory
|
||||
|
|
14
configure.ac
14
configure.ac
|
@ -557,15 +557,16 @@ no|avahi|bonjour)
|
|||
;;
|
||||
esac
|
||||
|
||||
enable_avahi=no
|
||||
enable_bounjour=no
|
||||
if test x$with_zeroconf != xno; then
|
||||
if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then
|
||||
PKG_CHECK_MODULES([AVAHI], [avahi-client avahi-glib],
|
||||
[found_avahi=1;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])]
|
||||
MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS",
|
||||
[found_avahi=0])
|
||||
[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")
|
||||
fi
|
||||
|
||||
if test x$found_avahi = x1; then
|
||||
if test x$enable_avahi = xyes; then
|
||||
with_zeroconf=avahi
|
||||
elif test x$with_zeroconf = xavahi; then
|
||||
AC_MSG_ERROR([Avahi support requested but not found])
|
||||
|
@ -573,13 +574,12 @@ if test x$with_zeroconf != xno; then
|
|||
|
||||
if test x$with_zeroconf = xbonjour || test x$with_zeroconf = xauto; then
|
||||
AC_CHECK_HEADER(dns_sd.h,
|
||||
[found_bonjour=1;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])],
|
||||
[found_bonjour=0])
|
||||
[enable_bonjour=yes;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])])
|
||||
AC_CHECK_LIB(dns_sd, DNSServiceRegister,
|
||||
MPD_LIBS="$MPD_LIBS -ldns_sd")
|
||||
fi
|
||||
|
||||
if test x$found_bonjour = x1; then
|
||||
if test x$enable_bonjour = xyes; then
|
||||
with_zeroconf=bonjour
|
||||
elif test x$with_zeroconf = xbonjour; then
|
||||
AC_MSG_ERROR([Bonjour support requested but not found])
|
||||
|
|
134
doc/protocol.xml
134
doc/protocol.xml
|
@ -8,18 +8,54 @@
|
|||
<title>General protocol syntax</title>
|
||||
|
||||
<section>
|
||||
<title>Requests</title>
|
||||
<title>Protocol overview</title>
|
||||
|
||||
<para>
|
||||
If arguments contain spaces, they should be surrounded by double quotation
|
||||
marks.
|
||||
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>
|
||||
The client transmits a command sequence, terminated by the
|
||||
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>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Requests</title>
|
||||
|
||||
<cmdsynopsis>
|
||||
<command>COMMAND</command>
|
||||
<arg rep="repeat"><replaceable>ARG</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
|
||||
<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
|
||||
UTF-8. (Note: In UTF-8 all standard ansi characters, 0-127 are
|
||||
|
@ -38,13 +74,97 @@
|
|||
<title>Responses</title>
|
||||
|
||||
<para>
|
||||
A command returns <returnvalue>OK</returnvalue> on completion
|
||||
or <returnvalue>ACK some error</returnvalue> on failure.
|
||||
These denote the end of command execution.
|
||||
A command returns <returnvalue>OK</returnvalue> on completion or
|
||||
<returnvalue>ACK some error</returnvalue> on failure. These
|
||||
denote the end of command execution.
|
||||
</para>
|
||||
|
||||
<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>
|
||||
<section id="command_lists">
|
||||
<title>Command lists</title>
|
||||
|
||||
<para>
|
||||
|
|
|
@ -456,7 +456,7 @@ cd mpd-version</programlisting>
|
|||
</para>
|
||||
|
||||
<para>
|
||||
To configure a filter, add a
|
||||
To configure a playlist plugin, add a
|
||||
<varname>playlist_plugin</varname> block to
|
||||
<filename>mpd.conf</filename>:
|
||||
</para>
|
||||
|
|
|
@ -60,8 +60,10 @@ ape_scan_internal(FILE *fp, tag_ape_callback_t callback, void *ctx)
|
|||
assert(remaining > 10);
|
||||
|
||||
char *buffer = g_malloc(remaining);
|
||||
if (fread(buffer, 1, remaining, fp) != remaining)
|
||||
if (fread(buffer, 1, remaining, fp) != remaining) {
|
||||
g_free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read tags */
|
||||
unsigned n = GUINT32_FROM_LE(footer.count);
|
||||
|
|
11
src/conf.c
11
src/conf.c
|
@ -372,6 +372,7 @@ config_read_file(const char *file, GError **error_r)
|
|||
assert(*line != 0);
|
||||
g_propagate_prefixed_error(error_r, error,
|
||||
"line %i: ", count);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -383,6 +384,7 @@ config_read_file(const char *file, GError **error_r)
|
|||
g_set_error(error_r, config_quark(), 0,
|
||||
"unrecognized parameter in config file at "
|
||||
"line %i: %s\n", count, name);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -392,6 +394,7 @@ config_read_file(const char *file, GError **error_r)
|
|||
"config parameter \"%s\" is first defined "
|
||||
"on line %i and redefined on line %i\n",
|
||||
name, param->line, count);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -403,6 +406,7 @@ config_read_file(const char *file, GError **error_r)
|
|||
if (*line != '{') {
|
||||
g_set_error(error_r, config_quark(), 0,
|
||||
"line %i: '{' expected", count);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -411,12 +415,15 @@ config_read_file(const char *file, GError **error_r)
|
|||
g_set_error(error_r, config_quark(), 0,
|
||||
"line %i: Unknown tokens after '{'",
|
||||
count);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
param = config_read_block(fp, &count, string, error_r);
|
||||
if (param == NULL)
|
||||
if (param == NULL) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* a string value */
|
||||
|
||||
|
@ -433,6 +440,7 @@ config_read_file(const char *file, GError **error_r)
|
|||
g_error_free(error);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -440,6 +448,7 @@ config_read_file(const char *file, GError **error_r)
|
|||
g_set_error(error_r, config_quark(), 0,
|
||||
"line %i: Unknown tokens after value",
|
||||
count);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ db_check(void)
|
|||
}
|
||||
|
||||
/* 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",
|
||||
dirPath, strerror(errno));
|
||||
g_free(dirPath);
|
||||
|
|
|
@ -138,6 +138,33 @@ mpd_ffmpeg_stream_open(struct decoder *decoder, struct input_stream *input)
|
|||
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
|
||||
mpd_ffmpeg_stream_close(struct mpd_ffmpeg_stream *stream)
|
||||
{
|
||||
|
@ -317,9 +344,9 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
|
|||
}
|
||||
|
||||
//ffmpeg works with ours "fileops" helper
|
||||
AVFormatContext *format_context;
|
||||
if (av_open_input_stream(&format_context, stream->io, input->uri,
|
||||
input_format, NULL) != 0) {
|
||||
AVFormatContext *format_context = NULL;
|
||||
if (mpd_ffmpeg_open_input(&format_context, stream->io, input->uri,
|
||||
input_format) != 0) {
|
||||
g_warning("Open failed\n");
|
||||
mpd_ffmpeg_stream_close(stream);
|
||||
return;
|
||||
|
@ -441,13 +468,26 @@ static const ffmpeg_tag_map ffmpeg_tag_maps[] = {
|
|||
};
|
||||
|
||||
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)
|
||||
{
|
||||
#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;
|
||||
|
||||
while ((mt = av_metadata_get(m, tag_map.name, mt, 0)) != NULL)
|
||||
tag_add_item(tag, tag_map.type, mt->value);
|
||||
#endif
|
||||
|
||||
return mt != NULL;
|
||||
}
|
||||
|
||||
|
@ -463,9 +503,9 @@ ffmpeg_stream_tag(struct input_stream *is)
|
|||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
AVFormatContext *f;
|
||||
if (av_open_input_stream(&f, stream->io, is->uri,
|
||||
input_format, NULL) != 0) {
|
||||
AVFormatContext *f = NULL;
|
||||
if (mpd_ffmpeg_open_input(&f, stream->io, is->uri,
|
||||
input_format) != 0) {
|
||||
mpd_ffmpeg_stream_close(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -224,7 +224,8 @@ flac_tag_apply_metadata(struct tag *tag, const char *track,
|
|||
break;
|
||||
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
tag->time = flac_duration(&block->data.stream_info);
|
||||
if (block->data.stream_info.sample_rate > 0)
|
||||
tag->time = flac_duration(&block->data.stream_info);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#ifndef MPD_FLAC_METADATA_H
|
||||
#define MPD_FLAC_METADATA_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <FLAC/metadata.h>
|
||||
|
||||
|
@ -29,6 +30,8 @@ struct replay_gain_info;
|
|||
static inline unsigned
|
||||
flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
|
||||
{
|
||||
assert(stream_info->sample_rate > 0);
|
||||
|
||||
return (stream_info->total_samples + stream_info->sample_rate - 1) /
|
||||
stream_info->sample_rate;
|
||||
}
|
||||
|
|
|
@ -106,12 +106,14 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
|
|||
g_set_error(error, ao_output_quark(), 0,
|
||||
"\"%s\" is not a valid ao driver",
|
||||
value);
|
||||
g_free(ad);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ai = ao_driver_info(ad->driver)) == NULL) {
|
||||
g_set_error(error, ao_output_quark(), 0,
|
||||
"problems getting driver info");
|
||||
g_free(ad);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -129,6 +131,7 @@ ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
|
|||
g_set_error(error, ao_output_quark(), 0,
|
||||
"problems parsing options \"%s\"",
|
||||
options[i]);
|
||||
g_free(ad);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
|
|||
if (encoder_plugin == NULL) {
|
||||
g_set_error(error, httpd_output_quark(), 0,
|
||||
"No such encoder: %s", encoder_name);
|
||||
g_free(httpd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,23 +79,27 @@ recorder_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
|
|||
if (encoder_plugin == NULL) {
|
||||
g_set_error(error_r, recorder_output_quark(), 0,
|
||||
"No such encoder: %s", encoder_name);
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
recorder->path = config_get_block_string(param, "path", NULL);
|
||||
if (recorder->path == NULL) {
|
||||
g_set_error(error_r, recorder_output_quark(), 0,
|
||||
"'path' not configured");
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* initialize encoder */
|
||||
|
||||
recorder->encoder = encoder_init(encoder_plugin, param, error_r);
|
||||
if (recorder->encoder == NULL)
|
||||
return NULL;
|
||||
goto failure;
|
||||
|
||||
return recorder;
|
||||
|
||||
failure:
|
||||
g_free(recorder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -152,7 +152,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
if (port == 0) {
|
||||
g_set_error(error, shout_output_quark(), 0,
|
||||
"shout port must be configured");
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
check_block_param("password");
|
||||
|
@ -174,21 +174,21 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
"shout quality \"%s\" is not a number in the "
|
||||
"range -1 to 10, line %i",
|
||||
value, param->line);
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (config_get_block_string(param, "bitrate", NULL) != NULL) {
|
||||
g_set_error(error, shout_output_quark(), 0,
|
||||
"quality and bitrate are "
|
||||
"both defined");
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
value = config_get_block_string(param, "bitrate", NULL);
|
||||
if (value == NULL) {
|
||||
g_set_error(error, shout_output_quark(), 0,
|
||||
"neither bitrate nor quality defined");
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
sd->bitrate = strtol(value, &test, 10);
|
||||
|
@ -196,7 +196,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
if (*test != '\0' || sd->bitrate <= 0) {
|
||||
g_set_error(error, shout_output_quark(), 0,
|
||||
"bitrate must be a positive integer");
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,12 +206,12 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
g_set_error(error, shout_output_quark(), 0,
|
||||
"couldn't find shout encoder plugin \"%s\"",
|
||||
encoding);
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
sd->encoder = encoder_init(encoder_plugin, param, error);
|
||||
if (sd->encoder == NULL)
|
||||
return NULL;
|
||||
goto failure;
|
||||
|
||||
if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0)
|
||||
shout_format = SHOUT_FORMAT_MP3;
|
||||
|
@ -225,7 +225,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
g_set_error(error, shout_output_quark(), 0,
|
||||
"you cannot stream \"%s\" to shoutcast, use mp3",
|
||||
encoding);
|
||||
return NULL;
|
||||
goto failure;
|
||||
} else if (0 == strcmp(value, "shoutcast"))
|
||||
protocol = SHOUT_PROTOCOL_ICY;
|
||||
else if (0 == strcmp(value, "icecast1"))
|
||||
|
@ -237,7 +237,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
"shout protocol \"%s\" is not \"shoutcast\" or "
|
||||
"\"icecast1\"or \"icecast2\"",
|
||||
value);
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
protocol = SHOUT_PROTOCOL_HTTP;
|
||||
|
@ -256,7 +256,7 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
shout_set_agent(sd->shout_conn, "MPD") != SHOUTERR_SUCCESS) {
|
||||
g_set_error(error, shout_output_quark(), 0,
|
||||
"%s", shout_get_error(sd->shout_conn));
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* optional paramters */
|
||||
|
@ -267,14 +267,14 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
if (value != NULL && shout_set_genre(sd->shout_conn, value)) {
|
||||
g_set_error(error, shout_output_quark(), 0,
|
||||
"%s", shout_get_error(sd->shout_conn));
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
value = config_get_block_string(param, "description", NULL);
|
||||
if (value != NULL && shout_set_description(sd->shout_conn, value)) {
|
||||
g_set_error(error, shout_output_quark(), 0,
|
||||
"%s", shout_get_error(sd->shout_conn));
|
||||
return NULL;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
value = config_get_block_string(param, "url", NULL);
|
||||
|
@ -307,6 +307,10 @@ my_shout_init_driver(const struct audio_format *audio_format,
|
|||
}
|
||||
|
||||
return sd;
|
||||
|
||||
failure:
|
||||
free_shout_data(sd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -579,8 +579,10 @@ sticker_load(const char *type, const char *uri)
|
|||
bool success;
|
||||
|
||||
success = sticker_list_values(sticker->table, type, uri);
|
||||
if (!success)
|
||||
if (!success) {
|
||||
sticker_free(sticker);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_hash_table_size(sticker->table) == 0) {
|
||||
/* don't return empty sticker objects */
|
||||
|
|
|
@ -37,30 +37,28 @@ my_log_func(G_GNUC_UNUSED const gchar *log_domain,
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *path, *name, *value;
|
||||
GError *error = NULL;
|
||||
bool success;
|
||||
int ret;
|
||||
|
||||
if (argc != 3) {
|
||||
g_printerr("Usage: read_conf FILE SETTING\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
path = argv[1];
|
||||
name = argv[2];
|
||||
const char *path = argv[1];
|
||||
const char *name = argv[2];
|
||||
|
||||
g_log_set_default_handler(my_log_func, NULL);
|
||||
|
||||
config_global_init();
|
||||
success = config_read_file(path, &error);
|
||||
|
||||
GError *error = NULL;
|
||||
bool success = config_read_file(path, &error);
|
||||
if (!success) {
|
||||
g_printerr("%s:", error->message);
|
||||
g_error_free(error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
value = config_get_string(name, NULL);
|
||||
const char *value = config_get_string(name, NULL);
|
||||
int ret;
|
||||
if (value != NULL) {
|
||||
g_print("%s\n", value);
|
||||
ret = 0;
|
||||
|
@ -70,5 +68,5 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
config_global_finish();
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,6 @@ int main(int argc, char **argv)
|
|||
struct filter *filter;
|
||||
const struct audio_format *out_audio_format;
|
||||
char buffer[4096];
|
||||
size_t frame_size;
|
||||
|
||||
if (argc < 3 || argc > 4) {
|
||||
g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n");
|
||||
|
@ -162,8 +161,6 @@ int main(int argc, char **argv)
|
|||
g_printerr("audio_format=%s\n",
|
||||
audio_format_to_string(out_audio_format, &af_string));
|
||||
|
||||
frame_size = audio_format_frame_size(&audio_format);
|
||||
|
||||
/* play */
|
||||
|
||||
while (true) {
|
||||
|
|
Loading…
Reference in New Issue