aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/decoder/ffmpeg_decoder_plugin.c20
-rw-r--r--src/decoder_api.c6
-rw-r--r--src/directory.h2
-rw-r--r--src/encoder/flac_encoder.c36
-rw-r--r--src/encoder/null_encoder.c34
-rw-r--r--src/encoder/wave_encoder.c51
-rw-r--r--src/event_pipe.c7
-rw-r--r--src/fifo_buffer.c49
-rw-r--r--src/fifo_buffer.h25
-rw-r--r--src/growing_fifo.c90
-rw-r--r--src/growing_fifo.h73
-rw-r--r--src/mapper.c46
-rw-r--r--src/path.c16
-rw-r--r--src/pcm_buffer.c21
-rw-r--r--src/pcm_buffer.h6
-rw-r--r--src/stats.c2
-rw-r--r--src/update_walk.c4
17 files changed, 410 insertions, 78 deletions
diff --git a/src/decoder/ffmpeg_decoder_plugin.c b/src/decoder/ffmpeg_decoder_plugin.c
index 2923c1400..14727715b 100644
--- a/src/decoder/ffmpeg_decoder_plugin.c
+++ b/src/decoder/ffmpeg_decoder_plugin.c
@@ -400,13 +400,6 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
return;
}
- if (avcodec_open(codec_context, codec)<0) {
- g_warning("Could not open codec\n");
- av_close_input_stream(format_context);
- mpd_ffmpeg_stream_close(stream);
- return;
- }
-
GError *error = NULL;
struct audio_format audio_format;
if (!audio_format_init_checked(&audio_format,
@@ -415,7 +408,18 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
codec_context->channels, &error)) {
g_warning("%s", error->message);
g_error_free(error);
- avcodec_close(codec_context);
+ av_close_input_stream(format_context);
+ mpd_ffmpeg_stream_close(stream);
+ return;
+ }
+
+ /* the audio format must be read from AVCodecContext by now,
+ because avcodec_open() has been demonstrated to fill bogus
+ values into AVCodecContext.channels - a change that will be
+ reverted later by avcodec_decode_audio3() */
+
+ if (avcodec_open(codec_context, codec)<0) {
+ g_warning("Could not open codec\n");
av_close_input_stream(format_context);
mpd_ffmpeg_stream_close(stream);
return;
diff --git a/src/decoder_api.c b/src/decoder_api.c
index 9fdb71311..3d7f20c50 100644
--- a/src/decoder_api.c
+++ b/src/decoder_api.c
@@ -96,6 +96,12 @@ decoder_prepare_initial_seek(struct decoder *decoder)
return true;
if (decoder->initial_seek_pending) {
+ if (!dc->seekable) {
+ /* seeking is not possible */
+ decoder->initial_seek_pending = false;
+ return false;
+ }
+
if (dc->command == DECODE_COMMAND_NONE) {
/* begin initial seek */
diff --git a/src/directory.h b/src/directory.h
index ce9c96cd2..6f693ec44 100644
--- a/src/directory.h
+++ b/src/directory.h
@@ -46,7 +46,7 @@ struct directory {
time_t mtime;
ino_t inode;
dev_t device;
- unsigned stat; /* not needed if ino_t == dev_t == 0 is impossible */
+ bool have_stat; /* not needed if ino_t == dev_t == 0 is impossible */
char path[sizeof(long)];
};
diff --git a/src/encoder/flac_encoder.c b/src/encoder/flac_encoder.c
index 8b315d710..9f60bdae5 100644
--- a/src/encoder/flac_encoder.c
+++ b/src/encoder/flac_encoder.c
@@ -22,6 +22,8 @@
#include "encoder_plugin.h"
#include "audio_format.h"
#include "pcm_buffer.h"
+#include "fifo_buffer.h"
+#include "growing_fifo.h"
#include <assert.h>
#include <string.h>
@@ -38,8 +40,11 @@ struct flac_encoder {
struct pcm_buffer expand_buffer;
- struct pcm_buffer buffer;
- size_t buffer_length;
+ /**
+ * This buffer will hold encoded data from libFLAC until it is
+ * picked up with flac_encoder_read().
+ */
+ struct fifo_buffer *output_buffer;
};
extern const struct encoder_plugin flac_encoder_plugin;
@@ -140,11 +145,8 @@ flac_write_callback(G_GNUC_UNUSED const FLAC__StreamEncoder *fse,
{
struct flac_encoder *encoder = (struct flac_encoder *) client_data;
- char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length + bytes);
-
//transfer data to buffer
- memcpy( buffer + encoder->buffer_length, data, bytes);
- encoder->buffer_length += bytes;
+ growing_fifo_append(&encoder->output_buffer, data, bytes);
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
@@ -156,8 +158,8 @@ flac_encoder_close(struct encoder *_encoder)
FLAC__stream_encoder_delete(encoder->fse);
- pcm_buffer_deinit(&encoder->buffer);
pcm_buffer_deinit(&encoder->expand_buffer);
+ fifo_buffer_free(encoder->output_buffer);
}
static bool
@@ -201,10 +203,10 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format,
return false;
}
- encoder->buffer_length = 0;
- pcm_buffer_init(&encoder->buffer);
pcm_buffer_init(&encoder->expand_buffer);
+ encoder->output_buffer = growing_fifo_new();
+
/* this immediately outputs data through callback */
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
@@ -325,16 +327,18 @@ static size_t
flac_encoder_read(struct encoder *_encoder, void *dest, size_t length)
{
struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
- char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length);
-
- if (length > encoder->buffer_length)
- length = encoder->buffer_length;
- memcpy(dest, buffer, length);
+ size_t max_length;
+ const char *src = fifo_buffer_read(encoder->output_buffer,
+ &max_length);
+ if (src == NULL)
+ return 0;
- encoder->buffer_length -= length;
- memmove(buffer, buffer + length, encoder->buffer_length);
+ if (length > max_length)
+ length = max_length;
+ memcpy(dest, src, length);
+ fifo_buffer_consume(encoder->output_buffer, length);
return length;
}
diff --git a/src/encoder/null_encoder.c b/src/encoder/null_encoder.c
index e83eaf2ba..48cdf139b 100644
--- a/src/encoder/null_encoder.c
+++ b/src/encoder/null_encoder.c
@@ -20,7 +20,8 @@
#include "config.h"
#include "encoder_api.h"
#include "encoder_plugin.h"
-#include "pcm_buffer.h"
+#include "fifo_buffer.h"
+#include "growing_fifo.h"
#include <assert.h>
#include <string.h>
@@ -28,8 +29,7 @@
struct null_encoder {
struct encoder encoder;
- struct pcm_buffer buffer;
- size_t buffer_length;
+ struct fifo_buffer *buffer;
};
extern const struct encoder_plugin null_encoder_plugin;
@@ -65,7 +65,7 @@ null_encoder_close(struct encoder *_encoder)
{
struct null_encoder *encoder = (struct null_encoder *)_encoder;
- pcm_buffer_deinit(&encoder->buffer);
+ fifo_buffer_free(encoder->buffer);
}
@@ -76,9 +76,7 @@ null_encoder_open(struct encoder *_encoder,
{
struct null_encoder *encoder = (struct null_encoder *)_encoder;
- encoder->buffer_length = 0;
- pcm_buffer_init(&encoder->buffer);
-
+ encoder->buffer = growing_fifo_new();
return true;
}
@@ -88,28 +86,26 @@ null_encoder_write(struct encoder *_encoder,
G_GNUC_UNUSED GError **error)
{
struct null_encoder *encoder = (struct null_encoder *)_encoder;
- char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length + length);
-
- memcpy(buffer+encoder->buffer_length, data, length);
- encoder->buffer_length += length;
- return true;
+ growing_fifo_append(&encoder->buffer, data, length);
+ return length;
}
static size_t
null_encoder_read(struct encoder *_encoder, void *dest, size_t length)
{
struct null_encoder *encoder = (struct null_encoder *)_encoder;
- char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length);
-
- if (length > encoder->buffer_length)
- length = encoder->buffer_length;
- memcpy(dest, buffer, length);
+ size_t max_length;
+ const void *src = fifo_buffer_read(encoder->buffer, &max_length);
+ if (src == NULL)
+ return 0;
- encoder->buffer_length -= length;
- memmove(buffer, buffer + length, encoder->buffer_length);
+ if (length > max_length)
+ length = max_length;
+ memcpy(dest, src, length);
+ fifo_buffer_consume(encoder->buffer, length);
return length;
}
diff --git a/src/encoder/wave_encoder.c b/src/encoder/wave_encoder.c
index 6ebacab7d..67c3ce085 100644
--- a/src/encoder/wave_encoder.c
+++ b/src/encoder/wave_encoder.c
@@ -20,7 +20,8 @@
#include "config.h"
#include "encoder_api.h"
#include "encoder_plugin.h"
-#include "pcm_buffer.h"
+#include "fifo_buffer.h"
+#include "growing_fifo.h"
#include <assert.h>
#include <string.h>
@@ -29,8 +30,7 @@ struct wave_encoder {
struct encoder encoder;
unsigned bits;
- struct pcm_buffer buffer;
- size_t buffer_length;
+ struct fifo_buffer *buffer;
};
struct wave_header {
@@ -92,7 +92,6 @@ wave_encoder_init(G_GNUC_UNUSED const struct config_param *param,
encoder = g_new(struct wave_encoder, 1);
encoder_struct_init(&encoder->encoder, &wave_encoder_plugin);
- pcm_buffer_init(&encoder->buffer);
return &encoder->encoder;
}
@@ -102,7 +101,6 @@ wave_encoder_finish(struct encoder *_encoder)
{
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
- pcm_buffer_deinit(&encoder->buffer);
g_free(encoder);
}
@@ -112,7 +110,6 @@ wave_encoder_open(struct encoder *_encoder,
G_GNUC_UNUSED GError **error)
{
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
- void *buffer;
assert(audio_format_valid(audio_format));
@@ -125,6 +122,11 @@ wave_encoder_open(struct encoder *_encoder,
encoder->bits = 16;
break;
+ case SAMPLE_FORMAT_S24:
+ audio_format->format = SAMPLE_FORMAT_S24_P32;
+ encoder->bits = 24;
+ break;
+
case SAMPLE_FORMAT_S24_P32:
encoder->bits = 24;
break;
@@ -139,19 +141,29 @@ wave_encoder_open(struct encoder *_encoder,
break;
}
- buffer = pcm_buffer_get(&encoder->buffer, sizeof(struct wave_header) );
+ encoder->buffer = growing_fifo_new();
+ struct wave_header *header =
+ growing_fifo_write(&encoder->buffer, sizeof(*header));
/* create PCM wave header in initial buffer */
- fill_wave_header((struct wave_header *) buffer,
+ fill_wave_header(header,
audio_format->channels,
encoder->bits,
audio_format->sample_rate,
(encoder->bits / 8) * audio_format->channels );
+ fifo_buffer_append(encoder->buffer, sizeof(*header));
- encoder->buffer_length = sizeof(struct wave_header);
return true;
}
+static void
+wave_encoder_close(struct encoder *_encoder)
+{
+ struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
+
+ fifo_buffer_free(encoder->buffer);
+}
+
static inline size_t
pcm16_to_wave(uint16_t *dst16, const uint16_t *src16, size_t length)
{
@@ -198,9 +210,8 @@ wave_encoder_write(struct encoder *_encoder,
G_GNUC_UNUSED GError **error)
{
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
- void *dst;
- dst = pcm_buffer_get(&encoder->buffer, encoder->buffer_length + length);
+ void *dst = growing_fifo_write(&encoder->buffer, length);
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
switch (encoder->bits) {
@@ -232,7 +243,7 @@ wave_encoder_write(struct encoder *_encoder,
#error G_BYTE_ORDER set to G_PDP_ENDIAN is not supported by wave_encoder
#endif
- encoder->buffer_length += length;
+ fifo_buffer_append(encoder->buffer, length);
return true;
}
@@ -240,16 +251,17 @@ static size_t
wave_encoder_read(struct encoder *_encoder, void *dest, size_t length)
{
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
- uint8_t *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length );
-
- if (length > encoder->buffer_length)
- length = encoder->buffer_length;
- memcpy(dest, buffer, length);
+ size_t max_length;
+ const void *src = fifo_buffer_read(encoder->buffer, &max_length);
+ if (src == NULL)
+ return 0;
- encoder->buffer_length -= length;
- memmove(buffer, buffer + length, encoder->buffer_length);
+ if (length > max_length)
+ length = max_length;
+ memcpy(dest, src, length);
+ fifo_buffer_consume(encoder->buffer, length);
return length;
}
@@ -264,6 +276,7 @@ const struct encoder_plugin wave_encoder_plugin = {
.init = wave_encoder_init,
.finish = wave_encoder_finish,
.open = wave_encoder_open,
+ .close = wave_encoder_close,
.write = wave_encoder_write,
.read = wave_encoder_read,
.get_mime_type = wave_encoder_get_mime_type,
diff --git a/src/event_pipe.c b/src/event_pipe.c
index 890d89f24..85fd6d917 100644
--- a/src/event_pipe.c
+++ b/src/event_pipe.c
@@ -21,7 +21,6 @@
#include "event_pipe.h"
#include "fd_util.h"
#include "mpd_error.h"
-#include "glib_socket.h"
#include <stdbool.h>
#include <assert.h>
@@ -95,7 +94,11 @@ void event_pipe_init(void)
if (ret < 0)
MPD_ERROR("Couldn't open pipe: %s", strerror(errno));
- channel = g_io_channel_new_socket(event_pipe[0]);
+#ifndef G_OS_WIN32
+ channel = g_io_channel_unix_new(event_pipe[0]);
+#else
+ channel = g_io_channel_win32_new_fd(event_pipe[0]);
+#endif
g_io_channel_set_encoding(channel, NULL, NULL);
g_io_channel_set_buffered(channel, false);
diff --git a/src/fifo_buffer.c b/src/fifo_buffer.c
index e5735f5eb..915fb0579 100644
--- a/src/fifo_buffer.c
+++ b/src/fifo_buffer.c
@@ -58,6 +58,39 @@ fifo_buffer_new(size_t size)
return buffer;
}
+static void
+fifo_buffer_move(struct fifo_buffer *buffer);
+
+struct fifo_buffer *
+fifo_buffer_realloc(struct fifo_buffer *buffer, size_t new_size)
+{
+ if (buffer == NULL)
+ return new_size > 0
+ ? fifo_buffer_new(new_size)
+ : NULL;
+
+ /* existing data must fit in new size */
+ assert(new_size >= buffer->end - buffer->start);
+
+ if (new_size == 0) {
+ fifo_buffer_free(buffer);
+ return NULL;
+ }
+
+ /* compress the buffer when we're shrinking and the tail of
+ the buffer would exceed the new size */
+ if (buffer->end > new_size)
+ fifo_buffer_move(buffer);
+
+ /* existing data must fit in new size: second check */
+ assert(buffer->end <= new_size);
+
+ buffer = g_realloc(buffer, sizeof(*buffer) - sizeof(buffer->buffer) +
+ new_size);
+ buffer->size = new_size;
+ return buffer;
+}
+
void
fifo_buffer_free(struct fifo_buffer *buffer)
{
@@ -66,6 +99,22 @@ fifo_buffer_free(struct fifo_buffer *buffer)
g_free(buffer);
}
+size_t
+fifo_buffer_capacity(const struct fifo_buffer *buffer)
+{
+ assert(buffer != NULL);
+
+ return buffer->size;
+}
+
+size_t
+fifo_buffer_available(const struct fifo_buffer *buffer)
+{
+ assert(buffer != NULL);
+
+ return buffer->end - buffer->start;
+}
+
void
fifo_buffer_clear(struct fifo_buffer *buffer)
{
diff --git a/src/fifo_buffer.h b/src/fifo_buffer.h
index 2730207b5..3bdb23938 100644
--- a/src/fifo_buffer.h
+++ b/src/fifo_buffer.h
@@ -57,12 +57,37 @@ struct fifo_buffer *
fifo_buffer_new(size_t size);
/**
+ * Change the capacity of the #fifo_buffer, while preserving existing
+ * data.
+ *
+ * @param buffer the old buffer, may be NULL
+ * @param new_size the requested new size of the #fifo_buffer; must
+ * not be smaller than the data which is stored in the old buffer
+ * @return the new buffer, may be NULL if the requested new size is 0
+ */
+struct fifo_buffer *
+fifo_buffer_realloc(struct fifo_buffer *buffer, size_t new_size);
+
+/**
* Frees the resources consumed by this #fifo_buffer object.
*/
void
fifo_buffer_free(struct fifo_buffer *buffer);
/**
+ * Return the capacity of the buffer, i.e. the size that was passed to
+ * fifo_buffer_new().
+ */
+size_t
+fifo_buffer_capacity(const struct fifo_buffer *buffer);
+
+/**
+ * Return the number of bytes currently stored in the buffer.
+ */
+size_t
+fifo_buffer_available(const struct fifo_buffer *buffer);
+
+/**
* Clears all data currently in this #fifo_buffer object. This does
* not overwrite the actuall buffer; it just resets the internal
* pointers.
diff --git a/src/growing_fifo.c b/src/growing_fifo.c
new file mode 100644
index 000000000..88431f60e
--- /dev/null
+++ b/src/growing_fifo.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "growing_fifo.h"
+#include "fifo_buffer.h"
+
+#include <assert.h>
+#include <string.h>
+
+/**
+ * Align buffer sizes at 8 kB boundaries. Must be a power of two.
+ */
+static const size_t GROWING_FIFO_ALIGN = 8192;
+
+/**
+ * Align the specified size to the next #GROWING_FIFO_ALIGN boundary.
+ */
+static size_t
+align(size_t size)
+{
+ return ((size - 1) | (GROWING_FIFO_ALIGN - 1)) + 1;
+}
+
+struct fifo_buffer *
+growing_fifo_new(void)
+{
+ return fifo_buffer_new(GROWING_FIFO_ALIGN);
+}
+
+void *
+growing_fifo_write(struct fifo_buffer **buffer_p, size_t length)
+{
+ assert(buffer_p != NULL);
+
+ struct fifo_buffer *buffer = *buffer_p;
+ assert(buffer != NULL);
+
+ size_t max_length;
+ void *p = fifo_buffer_write(buffer, &max_length);
+ if (p != NULL && max_length >= length)
+ return p;
+
+ /* grow */
+ size_t new_size = fifo_buffer_available(buffer) + length;
+ assert(new_size > fifo_buffer_capacity(buffer));
+ *buffer_p = buffer = fifo_buffer_realloc(buffer, align(new_size));
+
+ /* try again */
+ p = fifo_buffer_write(buffer, &max_length);
+ assert(p != NULL);
+ assert(max_length >= length);
+
+ return p;
+}
+
+void
+growing_fifo_append(struct fifo_buffer **buffer_p,
+ const void *data, size_t length)
+{
+ void *p = growing_fifo_write(buffer_p, length);
+ memcpy(p, data, length);
+ fifo_buffer_append(*buffer_p, length);
+}
diff --git a/src/growing_fifo.h b/src/growing_fifo.h
new file mode 100644
index 000000000..723c3b3ff
--- /dev/null
+++ b/src/growing_fifo.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file
+ *
+ * Helper functions for our FIFO buffer library (fifo_buffer.h) that
+ * allows growing the buffer on demand.
+ *
+ * This library is not thread safe.
+ */
+
+#ifndef MPD_GROWING_FIFO_H
+#define MPD_GROWING_FIFO_H
+
+#include <stddef.h>
+
+struct fifo_buffer;
+
+/**
+ * Allocate a new #fifo_buffer with the default size.
+ */
+struct fifo_buffer *
+growing_fifo_new(void);
+
+/**
+ * Prepares writing to the buffer, see fifo_buffer_write() for
+ * details. The difference is that this function will automatically
+ * grow the buffer if it is too small.
+ *
+ * The caller is responsible for limiting the capacity of the buffer.
+ *
+ * @param length the number of bytes that will be written
+ * @return a pointer to the end of the buffer (will not be NULL)
+ */
+void *
+growing_fifo_write(struct fifo_buffer **buffer_p, size_t length);
+
+/**
+ * A helper function that combines growing_fifo_write(), memcpy(),
+ * fifo_buffer_append().
+ */
+void
+growing_fifo_append(struct fifo_buffer **buffer_p,
+ const void *data, size_t length);
+
+#endif
diff --git a/src/mapper.c b/src/mapper.c
index 091db50b0..4aa4e0b14 100644
--- a/src/mapper.c
+++ b/src/mapper.c
@@ -31,6 +31,10 @@
#include <assert.h>
#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
static char *music_dir;
static size_t music_dir_length;
@@ -52,24 +56,50 @@ strdup_chop_slash(const char *path_fs)
}
static void
+check_directory(const char *path)
+{
+ struct stat st;
+ if (stat(path, &st) < 0) {
+ g_warning("Failed to stat directory \"%s\": %s",
+ path, g_strerror(errno));
+ return;
+ }
+
+ if (!S_ISDIR(st.st_mode)) {
+ g_warning("Not a directory: %s", path);
+ return;
+ }
+
+#ifndef WIN32
+ char *x = g_build_filename(path, ".", NULL);
+ if (stat(x, &st) < 0 && errno == EACCES)
+ g_warning("No permission to traverse (\"execute\") directory: %s",
+ path);
+ g_free(x);
+#endif
+
+ DIR *dir = opendir(path);
+ if (dir == NULL && errno == EACCES)
+ g_warning("No permission to read directory: %s", path);
+ else
+ closedir(dir);
+}
+
+static void
mapper_set_music_dir(const char *path)
{
+ check_directory(path);
+
music_dir = strdup_chop_slash(path);
music_dir_length = strlen(music_dir);
-
- if (!g_file_test(music_dir, G_FILE_TEST_IS_DIR))
- g_warning("music directory is not a directory: \"%s\"",
- music_dir);
}
static void
mapper_set_playlist_dir(const char *path)
{
- playlist_dir = g_strdup(path);
+ check_directory(path);
- if (!g_file_test(playlist_dir, G_FILE_TEST_IS_DIR))
- g_warning("playlist directory is not a directory: \"%s\"",
- playlist_dir);
+ playlist_dir = g_strdup(path);
}
void mapper_init(const char *_music_dir, const char *_playlist_dir)
diff --git a/src/path.c b/src/path.c
index 42e5a5c2a..59a91a0f7 100644
--- a/src/path.c
+++ b/src/path.c
@@ -27,6 +27,11 @@
#include <assert.h>
#include <string.h>
+#ifdef G_OS_WIN32
+#include <windows.h> // for GetACP()
+#include <stdio.h> // for sprintf()
+#endif
+
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "path"
@@ -85,11 +90,22 @@ void path_global_init(void)
charset = config_get_string(CONF_FS_CHARSET, NULL);
if (charset == NULL) {
+#ifndef G_OS_WIN32
const gchar **encodings;
g_get_filename_charsets(&encodings);
if (encodings[0] != NULL && *encodings[0] != '\0')
charset = encodings[0];
+#else /* G_OS_WIN32 */
+ /* Glib claims that file system encoding is always utf-8
+ * on native Win32 (i.e. not Cygwin).
+ * However this is true only if <gstdio.h> helpers are used.
+ * MPD uses regular <stdio.h> functions.
+ * Those functions use encoding determined by GetACP(). */
+ char win_charset[13];
+ sprintf(win_charset, "cp%u", GetACP());
+ charset = win_charset;
+#endif
}
if (charset) {
diff --git a/src/pcm_buffer.c b/src/pcm_buffer.c
index 12d7194a6..b277e768e 100644
--- a/src/pcm_buffer.c
+++ b/src/pcm_buffer.c
@@ -1,5 +1,9 @@
/*
+<<<<<<< HEAD
* Copyright (C) 2003-2011 The Music Player Daemon Project
+=======
+ * Copyright (C) 2003-2010 The Music Player Daemon Project
+>>>>>>> v0.16.x
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,17 +23,30 @@
#include "pcm_buffer.h"
+/**
+ * Align the specified size to the next 8k boundary.
+ */
+G_GNUC_CONST
+static size_t
+align_8k(size_t size)
+{
+ return ((size - 1) | 0x1fff) + 1;
+}
+
void *
pcm_buffer_get(struct pcm_buffer *buffer, size_t size)
{
+ assert(buffer != NULL);
+
if (buffer->size < size) {
/* free the old buffer */
g_free(buffer->buffer);
- /* allocate a new buffer; align at 8 kB boundaries */
- buffer->size = ((size - 1) | 0x1fff) + 1;
+ buffer->size = align_8k(size);
buffer->buffer = g_malloc(buffer->size);
}
+ assert(buffer->size >= size);
+
return buffer->buffer;
}
diff --git a/src/pcm_buffer.h b/src/pcm_buffer.h
index 67973b750..502dd3db1 100644
--- a/src/pcm_buffer.h
+++ b/src/pcm_buffer.h
@@ -22,6 +22,8 @@
#include <glib.h>
+#include <assert.h>
+
/**
* Manager for a temporary buffer which grows as needed. We could
* allocate a new buffer every time pcm_convert() is called, but that
@@ -39,6 +41,8 @@ struct pcm_buffer {
static inline void
pcm_buffer_init(struct pcm_buffer *buffer)
{
+ assert(buffer != NULL);
+
buffer->buffer = NULL;
buffer->size = 0;
}
@@ -49,6 +53,8 @@ pcm_buffer_init(struct pcm_buffer *buffer)
static inline void
pcm_buffer_deinit(struct pcm_buffer *buffer)
{
+ assert(buffer != NULL);
+
g_free(buffer->buffer);
buffer->buffer = NULL;
diff --git a/src/stats.c b/src/stats.c
index ec39ff5b7..fe6a064a6 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -123,6 +123,6 @@ int stats_print(struct client *client)
(long)g_timer_elapsed(stats.timer, NULL),
(long)(pc_get_total_play_time(client->player_control) + 0.5),
stats.song_duration,
- db_get_mtime());
+ (long)db_get_mtime());
return 0;
}
diff --git a/src/update_walk.c b/src/update_walk.c
index e70ead173..1fabc8682 100644
--- a/src/update_walk.c
+++ b/src/update_walk.c
@@ -86,7 +86,7 @@ directory_set_stat(struct directory *dir, const struct stat *st)
{
dir->inode = st->st_ino;
dir->device = st->st_dev;
- dir->stat = 1;
+ dir->have_stat = true;
}
static void
@@ -346,7 +346,7 @@ inodeFoundInParent(struct directory *parent, ino_t inode, dev_t device)
{
#ifndef G_OS_WIN32
while (parent) {
- if (!parent->stat && statDirectory(parent) < 0)
+ if (!parent->have_stat && statDirectory(parent) < 0)
return -1;
if (parent->inode == inode && parent->device == device) {
g_debug("recursive directory found");