Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b1cc760aa5 | ||
![]() |
d66c055fec | ||
![]() |
915d1d0738 | ||
![]() |
8a6d448aaf | ||
![]() |
a1939f3966 | ||
![]() |
9179f108a5 | ||
![]() |
3411f6cffd | ||
![]() |
6c0f50efb5 | ||
![]() |
2234d491b7 | ||
![]() |
81aa58efa8 | ||
![]() |
83aac2a057 | ||
![]() |
f01d7d230b | ||
![]() |
8f7bc70bf5 | ||
![]() |
5a354a1ed4 | ||
![]() |
f4b707b4ca | ||
![]() |
cd69fee0a4 | ||
![]() |
23e46b38ca | ||
![]() |
7162fe85ce | ||
![]() |
16123f1b8e | ||
![]() |
21fdf47b56 | ||
![]() |
d1aee3ae74 | ||
![]() |
30847e6c77 | ||
![]() |
97f8e017c4 | ||
![]() |
f51ba6464a | ||
![]() |
77b95d08a5 | ||
![]() |
dca4d9cf83 | ||
![]() |
68f77e4163 | ||
![]() |
93a13b42dd | ||
![]() |
96fcf5e1a5 | ||
![]() |
937b2b1744 | ||
![]() |
8c0680f6b9 | ||
![]() |
b242175e18 | ||
![]() |
3de912e2b9 | ||
![]() |
04816a6369 | ||
![]() |
d083032236 | ||
![]() |
1a6ed81193 | ||
![]() |
b2b300b635 |
@@ -748,6 +748,7 @@ DOCBOOK_HTML =
|
||||
endif
|
||||
|
||||
doc/api/html/index.html: doc/doxygen.conf
|
||||
@mkdir -p $(@D)
|
||||
$(DOXYGEN) $<
|
||||
|
||||
all-local: $(DOCBOOK_HTML) doc/api/html/index.html
|
||||
|
40
NEWS
40
NEWS
@@ -1,3 +1,43 @@
|
||||
ver 0.15.7 (2009/12/27)
|
||||
* archive:
|
||||
- close archive when stream is closed
|
||||
- iso, zip: fixed memory leak in destructor
|
||||
* input:
|
||||
- file: don't fall back to parent directory
|
||||
- archive: fixed memory leak in error handler
|
||||
* tags:
|
||||
- id3: fix ID3v1 charset conversion
|
||||
* decoders:
|
||||
- eliminate jitter after seek failure
|
||||
- ffmpeg: don't try to force stereo
|
||||
- wavpack: allow fine-grained seeking
|
||||
* mixer: explicitly close all mixers on shutdown
|
||||
* mapper: fix memory leak when playlist_directory is not set
|
||||
* mapper: apply filesystem_charset to playlists
|
||||
* command: verify playlist name in the "rm" command
|
||||
* database: return multiple tag values per song
|
||||
|
||||
|
||||
ver 0.15.6 (2009/11/18)
|
||||
* input:
|
||||
- lastfm: fixed variable name in GLib<2.16 code path
|
||||
- input/mms: require libmms 0.4
|
||||
* archive:
|
||||
- zzip: require libzzip 0.13
|
||||
* tags:
|
||||
- id3: allow 4 MB RIFF/AIFF tags
|
||||
* decoders:
|
||||
- ffmpeg: convert metadata
|
||||
- ffmpeg: align the output buffer
|
||||
- oggflac: rewind stream after FLAC detection
|
||||
- flac: fixed CUE seeking range check
|
||||
- flac: fixed NULL pointer dereference in CUE code
|
||||
* output_thread: check again if output is open on PAUSE
|
||||
* update: delete ignored symlinks from database
|
||||
* database: increased maximum line length to 32 kB
|
||||
* sticker: added fallback for sqlite3_prepare_v2()
|
||||
|
||||
|
||||
ver 0.15.5 (2009/10/18)
|
||||
* input:
|
||||
- curl: don't abort if a packet has only metadata
|
||||
|
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.60)
|
||||
AC_INIT(mpd, 0.15.5, musicpd-dev-team@lists.sourceforge.net)
|
||||
AC_INIT(mpd, 0.15.7, musicpd-dev-team@lists.sourceforge.net)
|
||||
AC_CONFIG_SRCDIR([src/main.c])
|
||||
AM_INIT_AUTOMAKE([foreign 1.9 dist-bzip2])
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
@@ -303,7 +303,7 @@ AC_ARG_ENABLE(mms,
|
||||
[enable the MMS protocol with libmms]),,
|
||||
[enable_mms=auto])
|
||||
|
||||
MPD_AUTO_PKG(mms, MMS, [libmms],
|
||||
MPD_AUTO_PKG(mms, MMS, [libmms >= 0.4],
|
||||
[libmms mms:// protocol support], [libmms not found])
|
||||
if test x$enable_mms = xyes; then
|
||||
AC_DEFINE(ENABLE_MMS, 1,
|
||||
@@ -339,7 +339,7 @@ AC_ARG_ENABLE(zip,
|
||||
[enable zip archive support (default: disabled)]),,
|
||||
enable_zip=no)
|
||||
|
||||
MPD_AUTO_PKG(zip, ZZIP, [zziplib],
|
||||
MPD_AUTO_PKG(zip, ZZIP, [zziplib >= 0.13],
|
||||
[libzzip archive library], [libzzip not found])
|
||||
|
||||
AM_CONDITIONAL(HAVE_ZIP, test x$enable_zip = xyes)
|
||||
|
@@ -140,8 +140,8 @@ static void
|
||||
bz2_close(struct archive_file *file)
|
||||
{
|
||||
bz2_context *context = (bz2_context *) file;
|
||||
if (context->name)
|
||||
g_free(context->name);
|
||||
|
||||
g_free(context->name);
|
||||
|
||||
input_stream_close(&context->istream);
|
||||
g_free(context);
|
||||
@@ -173,6 +173,8 @@ bz2_is_close(struct input_stream *is)
|
||||
bz2_context *context = (bz2_context *) is->data;
|
||||
bz2_destroy(context);
|
||||
is->data = NULL;
|
||||
|
||||
bz2_close((struct archive_file *)context);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@@ -132,7 +132,8 @@ iso_close(struct archive_file *file)
|
||||
}
|
||||
//close archive
|
||||
iso9660_close(context->iso);
|
||||
context->iso = NULL;
|
||||
|
||||
g_free(context);
|
||||
}
|
||||
|
||||
/* single archive handling */
|
||||
@@ -165,6 +166,8 @@ iso_is_close(struct input_stream *is)
|
||||
{
|
||||
iso_context *context = (iso_context *) is->data;
|
||||
g_free(context->statbuf);
|
||||
|
||||
iso_close((struct archive_file *)context);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -99,7 +99,8 @@ zip_close(struct archive_file *file)
|
||||
}
|
||||
//close archive
|
||||
zzip_dir_close (context->dir);
|
||||
context->dir = NULL;
|
||||
|
||||
g_free(context);
|
||||
}
|
||||
|
||||
/* single archive handling */
|
||||
@@ -133,6 +134,8 @@ zip_is_close(struct input_stream *is)
|
||||
{
|
||||
zip_context *context = (zip_context *) is->data;
|
||||
zzip_file_close (context->file);
|
||||
|
||||
zip_close((struct archive_file *)context);
|
||||
}
|
||||
|
||||
static size_t
|
||||
|
@@ -73,6 +73,9 @@ struct archive_plugin {
|
||||
/**
|
||||
* Opens an input_stream of a file within the archive.
|
||||
*
|
||||
* If this function succeeds, then the #input_stream "owns"
|
||||
* the archive file and will automatically close it.
|
||||
*
|
||||
* @param path the path within the archive
|
||||
*/
|
||||
bool (*open_stream)(struct archive_file *, struct input_stream *is,
|
||||
|
@@ -246,7 +246,6 @@ visitTag(struct client *client, struct strset *set,
|
||||
for (unsigned i = 0; i < tag->num_items; i++) {
|
||||
if (tag->items[i]->type == tagType) {
|
||||
strset_add(set, tag->items[i]->value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -415,11 +415,11 @@ flac_vtrack_tnum(const char* fname)
|
||||
* another/better way would be to use tag struct
|
||||
*/
|
||||
char* ptr = strrchr(fname, '_');
|
||||
if (ptr == NULL)
|
||||
return 0;
|
||||
|
||||
// copy ascii tracknumber to int
|
||||
char vtrack[4];
|
||||
g_strlcpy(vtrack, ++ptr, 4);
|
||||
return (unsigned int)strtol(vtrack, NULL, 10);
|
||||
return (unsigned int)strtol(++ptr, NULL, 10);
|
||||
}
|
||||
|
||||
#endif /* FLAC_API_VERSION_CURRENT >= 7 */
|
||||
|
@@ -209,6 +209,21 @@ ffmpeg_helper(struct input_stream *input,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* On some platforms, libavcodec wants the output buffer aligned to 16
|
||||
* bytes (because it uses SSE/Altivec internally). This function
|
||||
* returns the aligned version of the specified buffer, and corrects
|
||||
* the buffer size.
|
||||
*/
|
||||
static void *
|
||||
align16(void *p, size_t *length_p)
|
||||
{
|
||||
unsigned add = 16 - (size_t)p % 16;
|
||||
|
||||
*length_p -= add;
|
||||
return (char *)p + add;
|
||||
}
|
||||
|
||||
static enum decoder_command
|
||||
ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
|
||||
const AVPacket *packet,
|
||||
@@ -217,7 +232,9 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
|
||||
{
|
||||
enum decoder_command cmd = DECODE_COMMAND_NONE;
|
||||
int position;
|
||||
uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
|
||||
uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 + 16];
|
||||
int16_t *aligned_buffer;
|
||||
size_t buffer_size;
|
||||
int len, audio_size;
|
||||
uint8_t *packet_data;
|
||||
int packet_size;
|
||||
@@ -225,11 +242,13 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
|
||||
packet_data = packet->data;
|
||||
packet_size = packet->size;
|
||||
|
||||
buffer_size = sizeof(audio_buf);
|
||||
aligned_buffer = align16(audio_buf, &buffer_size);
|
||||
|
||||
while ((packet_size > 0) && (cmd == DECODE_COMMAND_NONE)) {
|
||||
audio_size = sizeof(audio_buf);
|
||||
audio_size = buffer_size;
|
||||
len = avcodec_decode_audio2(codec_context,
|
||||
(int16_t *)audio_buf,
|
||||
&audio_size,
|
||||
aligned_buffer, &audio_size,
|
||||
packet_data, packet_size);
|
||||
|
||||
if (len < 0) {
|
||||
@@ -250,7 +269,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
|
||||
: 0;
|
||||
|
||||
cmd = decoder_data(decoder, is,
|
||||
audio_buf, audio_size,
|
||||
aligned_buffer, audio_size,
|
||||
position,
|
||||
codec_context->bit_rate / 1000, NULL);
|
||||
}
|
||||
@@ -270,10 +289,6 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
|
||||
|
||||
total_time = 0;
|
||||
|
||||
if (codec_context->channels > 2) {
|
||||
codec_context->channels = 2;
|
||||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(41<<8)+0)
|
||||
audio_format.bits = (uint8_t) av_get_bits_per_sample_format(codec_context->sample_fmt);
|
||||
#else
|
||||
@@ -352,17 +367,17 @@ ffmpeg_copy_metadata(struct tag *tag, AVMetadata *m,
|
||||
static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx)
|
||||
{
|
||||
struct tag *tag = (struct tag *) ctx->tag;
|
||||
const AVFormatContext *f = ctx->format_context;
|
||||
AVFormatContext *f = ctx->format_context;
|
||||
|
||||
tag->time = 0;
|
||||
if (f->duration != (int64_t)AV_NOPTS_VALUE)
|
||||
tag->time = f->duration / AV_TIME_BASE;
|
||||
|
||||
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
|
||||
av_metadata_conv(f, NULL, f->iformat->metadata_conv);
|
||||
|
||||
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_TITLE, "title");
|
||||
if (!ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_ARTIST, "author"))
|
||||
ffmpeg_copy_metadata(tag, f->metadata,
|
||||
TAG_ITEM_ARTIST, "artist");
|
||||
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_ARTIST, "author");
|
||||
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_ALBUM, "album");
|
||||
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_COMMENT, "comment");
|
||||
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_GENRE, "genre");
|
||||
|
@@ -629,21 +629,15 @@ flac_container_decode(struct decoder* decoder,
|
||||
FLAC__uint64 seek_sample = t_start +
|
||||
(decoder_seek_where(decoder) * data.audio_format.sample_rate);
|
||||
|
||||
//if (seek_sample >= t_start && seek_sample <= t_end && data.total_time > 30)
|
||||
if (seek_sample >= t_start && seek_sample <= t_end)
|
||||
{
|
||||
if (flac_seek_absolute(flac_dec, (FLAC__uint64)seek_sample))
|
||||
{
|
||||
data.time = (float)(seek_sample - t_start) /
|
||||
data.audio_format.sample_rate;
|
||||
data.position = 0;
|
||||
if (seek_sample >= t_start && seek_sample <= t_end &&
|
||||
flac_seek_absolute(flac_dec, (FLAC__uint64)seek_sample)) {
|
||||
data.time = (float)(seek_sample - t_start) /
|
||||
data.audio_format.sample_rate;
|
||||
data.position = 0;
|
||||
|
||||
decoder_command_finished(decoder);
|
||||
}
|
||||
else
|
||||
decoder_seek_error(decoder);
|
||||
//decoder_command_finished(decoder);
|
||||
}
|
||||
decoder_command_finished(decoder);
|
||||
} else
|
||||
decoder_seek_error(decoder);
|
||||
}
|
||||
else if (flac_get_state(flac_dec) == flac_decoder_eof)
|
||||
break;
|
||||
|
@@ -272,6 +272,10 @@ oggflac_tag_dup(const char *file)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* rewind the stream, because ogg_stream_type_detect() has
|
||||
moved it */
|
||||
input_stream_seek(&input_stream, 0, SEEK_SET);
|
||||
|
||||
flac_data_init(&data, NULL, &input_stream);
|
||||
|
||||
data.tag = tag_new();
|
||||
@@ -300,6 +304,10 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *input_stream)
|
||||
if (ogg_stream_type_detect(input_stream) != FLAC)
|
||||
return;
|
||||
|
||||
/* rewind the stream, because ogg_stream_type_detect() has
|
||||
moved it */
|
||||
input_stream_seek(input_stream, 0, SEEK_SET);
|
||||
|
||||
flac_data_init(&data, mpd_decoder, input_stream);
|
||||
|
||||
if (!(decoder = full_decoder_init_and_read_metadata(&data, 0))) {
|
||||
|
@@ -72,7 +72,7 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
|
||||
|
||||
switch (bytes_per_sample) {
|
||||
case 1: {
|
||||
uchar *dst = buffer;
|
||||
int8_t *dst = buffer;
|
||||
/*
|
||||
* The asserts like the following one are because we do the
|
||||
* formatting of samples within a single buffer. The size
|
||||
@@ -185,10 +185,9 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
|
||||
do {
|
||||
if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) {
|
||||
if (can_seek) {
|
||||
int where;
|
||||
unsigned where = decoder_seek_where(decoder) *
|
||||
audio_format.sample_rate;
|
||||
|
||||
where = decoder_seek_where(decoder);
|
||||
where *= audio_format.sample_rate;
|
||||
if (WavpackSeekSample(wpc, where)) {
|
||||
position = where;
|
||||
decoder_command_finished(decoder);
|
||||
|
@@ -93,7 +93,9 @@ void decoder_command_finished(G_GNUC_UNUSED struct decoder * decoder)
|
||||
dc.seek_error || decoder->seeking);
|
||||
assert(dc.pipe != NULL);
|
||||
|
||||
if (dc.command == DECODE_COMMAND_SEEK) {
|
||||
if (decoder->seeking) {
|
||||
decoder->seeking = false;
|
||||
|
||||
/* delete frames from the old song position */
|
||||
|
||||
if (decoder->chunk != NULL) {
|
||||
@@ -124,6 +126,8 @@ void decoder_seek_error(struct decoder * decoder)
|
||||
assert(dc.pipe != NULL);
|
||||
|
||||
dc.seek_error = true;
|
||||
decoder->seeking = false;
|
||||
|
||||
decoder_command_finished(decoder);
|
||||
}
|
||||
|
||||
|
@@ -26,9 +26,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define DECODE_TYPE_FILE 0
|
||||
#define DECODE_TYPE_URL 1
|
||||
|
||||
enum decoder_state {
|
||||
DECODE_STATE_STOP = 0,
|
||||
DECODE_STATE_START,
|
||||
|
@@ -66,6 +66,7 @@ input_archive_open(struct input_stream *is, const char *pathname)
|
||||
|
||||
if (!opened) {
|
||||
g_warning("open inarchive file %s failed\n\n",filename);
|
||||
arplug->close(file);
|
||||
} else {
|
||||
is->ready = true;
|
||||
}
|
||||
|
@@ -36,25 +36,14 @@ input_file_open(struct input_stream *is, const char *filename)
|
||||
int fd, ret;
|
||||
struct stat st;
|
||||
|
||||
char* pathname = g_strdup(filename);
|
||||
|
||||
if (filename[0] != '/')
|
||||
{
|
||||
g_free(pathname);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stat(filename, &st) < 0) {
|
||||
char* slash = strrchr(pathname, '/');
|
||||
*slash = '\0';
|
||||
}
|
||||
|
||||
fd = open(pathname, O_RDONLY);
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
is->error = errno;
|
||||
g_debug("Failed to open \"%s\": %s",
|
||||
pathname, g_strerror(errno));
|
||||
g_free(pathname);
|
||||
filename, g_strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -64,15 +53,13 @@ input_file_open(struct input_stream *is, const char *filename)
|
||||
if (ret < 0) {
|
||||
is->error = errno;
|
||||
close(fd);
|
||||
g_free(pathname);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
g_debug("Not a regular file: %s", pathname);
|
||||
g_debug("Not a regular file: %s", filename);
|
||||
is->error = EINVAL;
|
||||
close(fd);
|
||||
g_free(pathname);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -86,8 +73,6 @@ input_file_open(struct input_stream *is, const char *filename)
|
||||
is->data = GINT_TO_POINTER(fd);
|
||||
is->ready = true;
|
||||
|
||||
g_free(pathname);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -112,7 +112,7 @@ lastfm_input_open(struct input_stream *is, const char *url)
|
||||
#if GLIB_CHECK_VERSION(2,16,0)
|
||||
q = g_uri_escape_string(lastfm_user, NULL, false);
|
||||
#else
|
||||
q = g_strdup(lastfm_username);
|
||||
q = g_strdup(lastfm_user);
|
||||
#endif
|
||||
|
||||
#if GLIB_CHECK_VERSION(2,16,0)
|
||||
|
13
src/mapper.c
13
src/mapper.c
@@ -221,14 +221,19 @@ map_spl_path(void)
|
||||
char *
|
||||
map_spl_utf8_to_fs(const char *name)
|
||||
{
|
||||
char *filename = g_strconcat(name, PLAYLIST_FILE_SUFFIX, NULL);
|
||||
char *path;
|
||||
char *filename_utf8, *filename_fs, *path;
|
||||
|
||||
if (playlist_dir == NULL)
|
||||
return NULL;
|
||||
|
||||
path = g_build_filename(playlist_dir, filename, NULL);
|
||||
g_free(filename);
|
||||
filename_utf8 = g_strconcat(name, PLAYLIST_FILE_SUFFIX, NULL);
|
||||
filename_fs = utf8_to_fs_charset(filename_utf8);
|
||||
g_free(filename_utf8);
|
||||
if (filename_fs == NULL)
|
||||
return NULL;
|
||||
|
||||
path = g_build_filename(playlist_dir, filename_fs, NULL);
|
||||
g_free(filename_fs);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@@ -99,6 +99,8 @@ map_spl_path(void);
|
||||
* Maps a playlist name (without the ".m3u" suffix) to a file system
|
||||
* path. The return value is allocated on the heap and must be freed
|
||||
* with g_free().
|
||||
*
|
||||
* @return the path in file system encoding, or NULL if mapping failed
|
||||
*/
|
||||
char *
|
||||
map_spl_utf8_to_fs(const char *name);
|
||||
|
@@ -62,6 +62,10 @@ mixer_free(struct mixer *mixer)
|
||||
assert(mixer->plugin != NULL);
|
||||
assert(mixer->mutex != NULL);
|
||||
|
||||
/* mixers with the "global" flag set might still be open at
|
||||
this point (see mixer_auto_close()) */
|
||||
mixer_close(mixer);
|
||||
|
||||
g_mutex_free(mixer->mutex);
|
||||
|
||||
mixer->plugin->finish(mixer);
|
||||
|
@@ -248,6 +248,15 @@ static gpointer audio_output_task(gpointer arg)
|
||||
break;
|
||||
|
||||
case AO_COMMAND_PAUSE:
|
||||
if (!ao->open) {
|
||||
/* the output has failed after
|
||||
audio_output_all_pause() has
|
||||
submitted the PAUSE command; bail
|
||||
out */
|
||||
ao_command_finished(ao);
|
||||
break;
|
||||
}
|
||||
|
||||
ao_pause(ao);
|
||||
/* don't "break" here: this might cause
|
||||
ao_play() to be called when command==CLOSE
|
||||
|
@@ -71,12 +71,15 @@ spl_save_queue(const char *name_utf8, const struct queue *queue)
|
||||
char *path_fs;
|
||||
FILE *file;
|
||||
|
||||
if (map_spl_path() == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
|
||||
if (!spl_valid_name(name_utf8))
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
path_fs = map_spl_utf8_to_fs(name_utf8);
|
||||
if (path_fs == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
if (g_file_test(path_fs, G_FILE_TEST_EXISTS)) {
|
||||
g_free(path_fs);
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#include "song.h"
|
||||
#include "tag_save.h"
|
||||
#include "directory.h"
|
||||
#include "path.h"
|
||||
#include "tag.h"
|
||||
|
||||
#include <glib.h>
|
||||
@@ -113,12 +112,15 @@ matchesAnMpdTagItemKey(char *buffer, enum tag_type *itemType)
|
||||
void readSongInfoIntoList(FILE *fp, struct songvec *sv,
|
||||
struct directory *parent)
|
||||
{
|
||||
char buffer[MPD_PATH_MAX + 1024];
|
||||
enum {
|
||||
buffer_size = 32768,
|
||||
};
|
||||
char *buffer = g_malloc(buffer_size);
|
||||
struct song *song = NULL;
|
||||
enum tag_type itemType;
|
||||
const char *value;
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp) &&
|
||||
while (fgets(buffer, buffer_size, fp) &&
|
||||
!g_str_has_prefix(buffer, SONG_END)) {
|
||||
g_strchomp(buffer);
|
||||
|
||||
@@ -156,6 +158,8 @@ void readSongInfoIntoList(FILE *fp, struct songvec *sv,
|
||||
g_error("unknown line in db: %s", buffer);
|
||||
}
|
||||
|
||||
g_free(buffer);
|
||||
|
||||
if (song)
|
||||
insertSongIntoList(sv, song);
|
||||
}
|
||||
|
@@ -27,6 +27,10 @@
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "sticker"
|
||||
|
||||
#if SQLITE_VERSION_NUMBER < 3003009
|
||||
#define sqlite3_prepare_v2 sqlite3_prepare
|
||||
#endif
|
||||
|
||||
struct sticker {
|
||||
GHashTable *table;
|
||||
};
|
||||
|
@@ -152,9 +152,12 @@ spl_save(GPtrArray *list, const char *utf8path)
|
||||
|
||||
assert(utf8path != NULL);
|
||||
|
||||
if (map_spl_path() == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
|
||||
path_fs = map_spl_utf8_to_fs(utf8path);
|
||||
if (path_fs == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
while (!(file = fopen(path_fs, "w")) && errno == EINTR);
|
||||
g_free(path_fs);
|
||||
@@ -178,7 +181,7 @@ spl_load(const char *utf8path)
|
||||
char buffer[MPD_PATH_MAX];
|
||||
char *path_fs;
|
||||
|
||||
if (!spl_valid_name(utf8path))
|
||||
if (!spl_valid_name(utf8path) || map_spl_path() == NULL)
|
||||
return NULL;
|
||||
|
||||
path_fs = map_spl_utf8_to_fs(utf8path);
|
||||
@@ -299,12 +302,15 @@ spl_clear(const char *utf8path)
|
||||
char *path_fs;
|
||||
FILE *file;
|
||||
|
||||
if (map_spl_path() == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
|
||||
if (!spl_valid_name(utf8path))
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
path_fs = map_spl_utf8_to_fs(utf8path);
|
||||
if (path_fs == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
while (!(file = fopen(path_fs, "w")) && errno == EINTR);
|
||||
g_free(path_fs);
|
||||
@@ -323,9 +329,15 @@ spl_delete(const char *name_utf8)
|
||||
char *path_fs;
|
||||
int ret;
|
||||
|
||||
if (map_spl_path() == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
|
||||
if (!spl_valid_name(name_utf8))
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
path_fs = map_spl_utf8_to_fs(name_utf8);
|
||||
if (path_fs == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
ret = unlink(path_fs);
|
||||
g_free(path_fs);
|
||||
@@ -370,12 +382,15 @@ spl_append_song(const char *utf8path, struct song *song)
|
||||
struct stat st;
|
||||
char *path_fs;
|
||||
|
||||
if (map_spl_path() == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
|
||||
if (!spl_valid_name(utf8path))
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
path_fs = map_spl_utf8_to_fs(utf8path);
|
||||
if (path_fs == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
while (!(file = fopen(path_fs, "a")) && errno == EINTR);
|
||||
g_free(path_fs);
|
||||
@@ -445,6 +460,9 @@ spl_rename(const char *utf8from, const char *utf8to)
|
||||
char *from_path_fs, *to_path_fs;
|
||||
static enum playlist_result ret;
|
||||
|
||||
if (map_spl_path() == NULL)
|
||||
return PLAYLIST_RESULT_DISABLED;
|
||||
|
||||
if (!spl_valid_name(utf8from) || !spl_valid_name(utf8to))
|
||||
return PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
@@ -454,7 +472,7 @@ spl_rename(const char *utf8from, const char *utf8to)
|
||||
if (from_path_fs != NULL && to_path_fs != NULL)
|
||||
ret = spl_rename_internal(from_path_fs, to_path_fs);
|
||||
else
|
||||
ret = PLAYLIST_RESULT_DISABLED;
|
||||
ret = PLAYLIST_RESULT_BAD_NAME;
|
||||
|
||||
g_free(from_path_fs);
|
||||
g_free(to_path_fs);
|
||||
|
@@ -90,7 +90,7 @@ static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4,
|
||||
|
||||
utf8 = (id3_utf8_t *)
|
||||
g_convert_with_fallback((const char*)isostr, -1,
|
||||
encoding, "utf-8",
|
||||
"utf-8", encoding,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (utf8 == NULL) {
|
||||
g_debug("Unable to convert %s string to UTF-8: '%s'",
|
||||
@@ -481,7 +481,7 @@ tag_id3_riff_aiff_load(FILE *file)
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
|
||||
if (size > 256 * 1024)
|
||||
if (size > 4 * 1024 * 1024)
|
||||
/* too large, don't allocate so much memory */
|
||||
return NULL;
|
||||
|
||||
|
@@ -672,7 +672,11 @@ updateDirectory(struct directory *directory, const struct stat *st)
|
||||
continue;
|
||||
|
||||
utf8 = fs_charset_to_utf8(ent->d_name);
|
||||
if (utf8 == NULL || skip_symlink(directory, utf8)) {
|
||||
if (utf8 == NULL)
|
||||
continue;
|
||||
|
||||
if (skip_symlink(directory, utf8)) {
|
||||
delete_name_in(directory, utf8);
|
||||
g_free(utf8);
|
||||
continue;
|
||||
}
|
||||
|
113
test/run_input.c
113
test/run_input.c
@@ -17,11 +17,16 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "input_stream.h"
|
||||
#include "tag_pool.h"
|
||||
#include "tag_save.h"
|
||||
#include "conf.h"
|
||||
|
||||
#ifdef ENABLE_ARCHIVE
|
||||
#include "archive_list.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -36,14 +41,58 @@ my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level,
|
||||
g_printerr("%s\n", message);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
static int
|
||||
dump_input_stream(struct input_stream *is)
|
||||
{
|
||||
struct input_stream is;
|
||||
bool success;
|
||||
char buffer[4096];
|
||||
size_t num_read;
|
||||
ssize_t num_written;
|
||||
|
||||
/* wait until the stream becomes ready */
|
||||
|
||||
while (!is->ready) {
|
||||
int ret = input_stream_buffer(is);
|
||||
if (ret < 0)
|
||||
/* error */
|
||||
return 2;
|
||||
|
||||
if (ret == 0)
|
||||
/* nothing was buffered - wait */
|
||||
g_usleep(10000);
|
||||
}
|
||||
|
||||
/* print meta data */
|
||||
|
||||
if (is->mime != NULL)
|
||||
g_printerr("MIME type: %s\n", is->mime);
|
||||
|
||||
/* read data and tags from the stream */
|
||||
|
||||
while (!input_stream_eof(is)) {
|
||||
struct tag *tag = input_stream_tag(is);
|
||||
if (tag != NULL) {
|
||||
g_printerr("Received a tag:\n");
|
||||
tag_save(stderr, tag);
|
||||
tag_free(tag);
|
||||
}
|
||||
|
||||
num_read = input_stream_read(is, buffer, sizeof(buffer));
|
||||
if (num_read == 0)
|
||||
break;
|
||||
|
||||
num_written = write(1, buffer, num_read);
|
||||
if (num_written <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct input_stream is;
|
||||
int ret;
|
||||
|
||||
if (argc != 2) {
|
||||
g_printerr("Usage: run_input URI\n");
|
||||
return 1;
|
||||
@@ -58,57 +107,33 @@ int main(int argc, char **argv)
|
||||
|
||||
tag_pool_init();
|
||||
config_global_init();
|
||||
|
||||
#ifdef ENABLE_ARCHIVE
|
||||
archive_plugin_init_all();
|
||||
#endif
|
||||
|
||||
input_stream_global_init();
|
||||
|
||||
/* open the stream and wait until it becomes ready */
|
||||
/* open the stream and dump it */
|
||||
|
||||
success = input_stream_open(&is, argv[1]);
|
||||
if (!success) {
|
||||
if (input_stream_open(&is, argv[1])) {
|
||||
ret = dump_input_stream(&is);
|
||||
input_stream_close(&is);
|
||||
} else {
|
||||
g_printerr("input_stream_open() failed\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
while (!is.ready) {
|
||||
int ret = input_stream_buffer(&is);
|
||||
if (ret < 0)
|
||||
/* error */
|
||||
return 2;
|
||||
|
||||
if (ret == 0)
|
||||
/* nothing was buffered - wait */
|
||||
g_usleep(10000);
|
||||
}
|
||||
|
||||
/* print meta data */
|
||||
|
||||
if (is.mime != NULL)
|
||||
g_printerr("MIME type: %s\n", is.mime);
|
||||
|
||||
/* read data and tags from the stream */
|
||||
|
||||
while (!input_stream_eof(&is)) {
|
||||
struct tag *tag = input_stream_tag(&is);
|
||||
if (tag != NULL) {
|
||||
g_printerr("Received a tag:\n");
|
||||
tag_save(stderr, tag);
|
||||
tag_free(tag);
|
||||
}
|
||||
|
||||
num_read = input_stream_read(&is, buffer, sizeof(buffer));
|
||||
if (num_read == 0)
|
||||
break;
|
||||
|
||||
num_written = write(1, buffer, num_read);
|
||||
if (num_written <= 0)
|
||||
break;
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
/* deinitialize everything */
|
||||
|
||||
input_stream_close(&is);
|
||||
input_stream_global_finish();
|
||||
|
||||
#ifdef ENABLE_ARCHIVE
|
||||
archive_plugin_deinit_all();
|
||||
#endif
|
||||
|
||||
config_global_finish();
|
||||
tag_pool_deinit();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user