Merge branch 'v0.16.x'
Conflicts: Makefile.am NEWS configure.ac src/encoder/flac_encoder.c src/log.c src/pcm_buffer.c
This commit is contained in:
commit
4f093d5b97
10
Makefile.am
10
Makefile.am
@ -84,7 +84,6 @@ mpd_headers = \
|
||||
src/encoder_api.h \
|
||||
src/exclude.h \
|
||||
src/fd_util.h \
|
||||
src/fifo_buffer.h \
|
||||
src/glib_compat.h \
|
||||
src/update.h \
|
||||
src/update_internal.h \
|
||||
@ -258,7 +257,8 @@ src_mpd_SOURCES = \
|
||||
src/dirvec.c \
|
||||
src/exclude.c \
|
||||
src/fd_util.c \
|
||||
src/fifo_buffer.c \
|
||||
src/fifo_buffer.c src/fifo_buffer.h \
|
||||
src/growing_fifo.c src/growing_fifo.h \
|
||||
src/filter_config.c \
|
||||
src/filter_plugin.c \
|
||||
src/filter_registry.c \
|
||||
@ -1035,6 +1035,9 @@ test_run_decoder_SOURCES = test/run_decoder.c \
|
||||
src/audio_check.c \
|
||||
src/audio_format.c \
|
||||
src/timer.c \
|
||||
$(ARCHIVE_SRC) \
|
||||
$(INPUT_SRC) \
|
||||
$(TAG_SRC) \
|
||||
$(DECODER_SRC)
|
||||
|
||||
test_read_tags_LDADD = \
|
||||
@ -1093,6 +1096,7 @@ if ENABLE_ENCODER
|
||||
noinst_PROGRAMS += test/run_encoder
|
||||
test_run_encoder_SOURCES = test/run_encoder.c \
|
||||
test/stdbin.h \
|
||||
src/fifo_buffer.c src/growing_fifo.c \
|
||||
src/conf.c src/tokenizer.c \
|
||||
src/utils.c src/string_util.c \
|
||||
src/tag.c src/tag_pool.c \
|
||||
@ -1148,7 +1152,7 @@ test_run_output_SOURCES = test/run_output.c \
|
||||
src/audio_parser.c \
|
||||
src/timer.c \
|
||||
src/tag.c src/tag_pool.c \
|
||||
src/fifo_buffer.c \
|
||||
src/fifo_buffer.c src/growing_fifo.c \
|
||||
src/page.c \
|
||||
src/socket_util.c \
|
||||
src/resolver.c \
|
||||
|
15
NEWS
15
NEWS
@ -28,6 +28,21 @@ ver 0.17 (2011/??/??)
|
||||
* support floating point samples
|
||||
|
||||
|
||||
ver 0.16.6 (2010/??/??)
|
||||
* decoder:
|
||||
- fix assertion failure when resuming streams
|
||||
- ffmpeg: work around bogus channel count
|
||||
* encoder:
|
||||
- flac, null, wave: fix buffer corruption bug
|
||||
- wave: support packed 24 bit samples
|
||||
* mapper: fix the bogus "not a directory" error message
|
||||
* mapper: check "x" and "r" permissions on music directory
|
||||
* log: print reason for failure
|
||||
* event_pipe: fix WIN32 regression
|
||||
* define WINVER in ./configure
|
||||
* WIN32: autodetect filesystem encoding
|
||||
|
||||
|
||||
ver 0.16.5 (2010/10/09)
|
||||
* configure.ac
|
||||
- disable assertions in the non-debugging build
|
||||
|
@ -65,6 +65,7 @@ AC_CANONICAL_HOST
|
||||
|
||||
case "$host_os" in
|
||||
mingw32* | windows*)
|
||||
AM_CPPFLAGS="$AM_CPPFLAGS -DWINVER=0x0501"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
;;
|
||||
esac
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)];
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
size_t max_length;
|
||||
const char *src = fifo_buffer_read(encoder->output_buffer,
|
||||
&max_length);
|
||||
if (src == NULL)
|
||||
return 0;
|
||||
|
||||
memcpy(dest, buffer, length);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
size_t max_length;
|
||||
const void *src = fifo_buffer_read(encoder->buffer, &max_length);
|
||||
if (src == NULL)
|
||||
return 0;
|
||||
|
||||
memcpy(dest, buffer, length);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
size_t max_length;
|
||||
const void *src = fifo_buffer_read(encoder->buffer, &max_length);
|
||||
if (src == NULL)
|
||||
return 0;
|
||||
|
||||
memcpy(dest, buffer, length);
|
||||
|
||||
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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -56,12 +56,37 @@ struct fifo_buffer;
|
||||
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
|
||||
|
90
src/growing_fifo.c
Normal file
90
src/growing_fifo.c
Normal file
@ -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);
|
||||
}
|
73
src/growing_fifo.h
Normal file
73
src/growing_fifo.h
Normal file
@ -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
|
46
src/mapper.c
46
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;
|
||||
@ -51,25 +55,51 @@ strdup_chop_slash(const char *path_fs)
|
||||
return g_strndup(path_fs, length);
|
||||
}
|
||||
|
||||
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)
|
||||
|
16
src/path.c
16
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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user