Compare commits

...

37 Commits

Author SHA1 Message Date
Avuton Olrich
b1cc760aa5 mpd version 0.15.7 2009-12-27 08:31:47 -08:00
Max Kellermann
d66c055fec dbUtils: return multiple tag values per song
When collecting tag values for the result set, add all of a song's tag
values of the searched type.  This affects the "list" command.
Previously, "list" only considered the first tag value of a song.
2009-12-27 16:49:04 +01:00
Max Kellermann
915d1d0738 decoder_thread: eliminate jitter after seek failure
Don't clear the music pipe when seeking has failed - check the
"seeking" flag instead of "command==SEEK".  Clear the "seeking" flag
in decoder_seek_error().
2009-12-26 02:58:30 +01:00
Max Kellermann
8a6d448aaf decoder/wavpack: allow fine-grained seeking
First multiply the floating point return value of
decoder_seek_where(), then cast to integer.
2009-12-26 02:58:30 +01:00
Max Kellermann
a1939f3966 Makefile.am: create doxygen output directory 2009-12-26 02:58:30 +01:00
Max Kellermann
9179f108a5 iso, zip: fixed memory leak in destructor
Free the "context" pointer in the method archive_plugin.close().
2009-12-15 19:57:00 +01:00
Max Kellermann
3411f6cffd archive: close archive when stream is closed
Fixes a memory leak: the "archive" input plugin opens the archive, but
never closes it.  This patch moves the responsibility for doing that
to archive_plugin.open_stream().  This is an slight internal API
change, but it is the simplest and least intrusive fix for the memory
leak.
2009-12-15 19:45:50 +01:00
Max Kellermann
6c0f50efb5 archive/bz2: removed NULL check before g_free()
g_free(NULL) is allowed.
2009-12-15 19:42:54 +01:00
Max Kellermann
2234d491b7 input/archive: close the archive file on error
Fixed memory leak in error handler.
2009-12-15 19:41:00 +01:00
Max Kellermann
81aa58efa8 test/run_input: deinitialize everything after open() error
This enables valgrind debugging after an error occurred.
2009-12-15 19:40:47 +01:00
Max Kellermann
83aac2a057 test/run_input: initialize archive plugins
Enable archive plugin debugging.
2009-12-15 19:40:14 +01:00
Max Kellermann
f01d7d230b input/file: don't fall back to parent directory
This code has never made any sense, and has broken some of the archive
plugin.
2009-12-15 19:16:28 +01:00
Max Kellermann
8f7bc70bf5 decoder/wavpack: don't use the nonstandard "uchar" type
Use the signed C99 type int8_t instead.
2009-12-11 12:45:57 +01:00
Max Kellermann
5a354a1ed4 mixer: explicitly close all mixers on shutdown
Mixers with the "global" flag set aren't closed automatically when the
output device is closed.  Thus, they might still be open when MPD
shuts down.
2009-12-08 08:47:47 +01:00
Max Kellermann
f4b707b4ca mapper: apply filesystem_charset to playlists
This fixes an inconsistency in the stored playlist subsystem: when
obtaining the list of playlists (listplaylist, listplaylistinfo), the
file names in the playlist directory are converted to UTF-8 (according
to filesystem_charset), but when saving or loading playlists, the
filesystem_charset setting was ignored.
2009-12-08 08:33:14 +01:00
Max Kellermann
cd69fee0a4 command: verify playlist name in the "rm" command
Call spl_valid_name() in spl_delete().
2009-12-08 08:32:26 +01:00
Max Kellermann
23e46b38ca mapper: fix memory leak when playlist_directory is not set
Don't allocate the file name before the playlist_dir==NULL check.
2009-12-08 08:06:10 +01:00
svitoos
7162fe85ce tag_id3: fix ID3v1 charset conversion
If we define id3v1_encoding, then the tags are not added to the
database.
2009-11-30 17:42:46 +01:00
Max Kellermann
16123f1b8e ffmpeg: don't try to force stereo
The plugin code tried to force libavcodec to supply stereo samples.
That however has never actually worked.  By removing this code, we are
able to play surround files for the first time.
2009-11-30 09:59:05 +01:00
Max Kellermann
21fdf47b56 decoder/flac: fixed compiler warning
Removed the "vtrack" local variable (which triggered a gcc warning
because it was after the newly introduced NULL check), and run
strtol() on the original parameter.
2009-11-19 19:49:44 +01:00
Avuton Olrich
d1aee3ae74 Modify version string to post-release version 0.15.7~git 2009-11-18 18:49:25 -08:00
Avuton Olrich
30847e6c77 mpd version 0.15.6 2009-11-18 18:49:25 -08:00
Max Kellermann
97f8e017c4 decoder/flac: fixed NULL pointer dereference in CUE code
The function flac_vtrack_tnum() was missing a strrchr()==NULL check.
2009-11-18 19:55:38 +01:00
Max Kellermann
f51ba6464a id3: allow 4 MB RIFF/AIFF tags
Allow RIFF/AIFF ID3 tags up to 4 MB (old limit was 256 kB).  This
might still be too small for some users, and when somebody complains,
we might do something more clever (like streaming the data into
libid3tag?).
2009-11-15 18:44:53 +01:00
Max Kellermann
77b95d08a5 decoder/ffmpeg: align the output buffer
On some platforms, libavcodec wants the output buffer aligned to 16
bytes (because it uses SSE/Altivec internally).  It will segfault when
you don't obey this rule.
2009-11-15 17:39:09 +01:00
Max Kellermann
dca4d9cf83 decoder/flac: fixed CUE seeking range check
If flac_container_decode() gets a seek destination which is out of
range, it ignores the SEEK command (never finishes it).  This leads to
MPD lockup, because the player thread waits for completion.
2009-11-11 08:55:55 +01:00
Max Kellermann
68f77e4163 oggflac: rewind stream after FLAC detection
The oggflac plugin has been completely broken for quite a while and
nobody has noticed - maybe we should remove it?
2009-11-11 08:14:37 +01:00
Max Kellermann
93a13b42dd zzip: require libzzip 0.13
We need the function zzip_file_stat().
2009-11-10 21:00:10 +01:00
Max Kellermann
96fcf5e1a5 input/mms: require libmms 0.4
We're using API functions which are not available in 0.3.
2009-11-10 20:57:10 +01:00
Max Kellermann
937b2b1744 sticker: added fallback for sqlite3_prepare_v2()
This function was not present in SQLite < 3.4.
2009-11-10 20:55:29 +01:00
Max Kellermann
8c0680f6b9 input/lastfm: fixed variable name in GLib<2.16 code path
Should be "lastfm_user", not "lastfm_username".
2009-11-10 20:54:17 +01:00
Max Kellermann
b242175e18 song_save: increased maximum line length to 32 kB
The line buffer had a fixed size of 5 kB, and was allocated on the
stack.  This was too small for some users.  As a hotfix, we're
increasing the buffer size to 32 kB now, allocated on the heap.  In
MPD 0.16, we'll switch to dynamic allocation.
2009-11-01 15:27:55 +01:00
Max Kellermann
3de912e2b9 decoder_control: removed unused DECODE_TYPE macros 2009-10-31 18:03:50 +01:00
Max Kellermann
04816a6369 decoder/ffmpeg: convert metadata
Convert the metadata with the libavformat function av_metadata_conv().
This ensures that canonical tag names are provided by libavformat, and
we can remove the "artist" vs "author" workaround.
2009-10-28 22:12:22 +01:00
Max Kellermann
d083032236 update: delete ignored symlinks from database
When you disable the "follow_outside_symlinks" or the
"follow_inside_symlinks" setting, the next update should remove the
now-ignored files from the database.
2009-10-27 22:06:28 +01:00
Max Kellermann
1a6ed81193 output_thread: check again if output is open on PAUSE
Basically the same as the 0.15.5 patch "check again if output is open
on CANCEL".  Same race condition, same fix.
2009-10-21 08:07:07 +02:00
Avuton Olrich
b2b300b635 Modify version string to post-release version 0.15.6~git 2009-10-18 09:50:17 -07:00
29 changed files with 258 additions and 126 deletions

@@ -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

@@ -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)

@@ -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;
}

@@ -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;
}