Commit eaff52fa authored by Alexey Rusakov's avatar Alexey Rusakov

Merge commit 'release-0.15.5' into alt

parents 7fe0a63d 7df1a2c7
ver 0.15.5 (2009/10/18)
* input:
- curl: don't abort if a packet has only metadata
- curl: fixed endless loop during buffering
* tags:
- riff, aiff: fixed "limited range" gcc warning
* decoders:
- flac: fixed two memory leaks in the CUE tag loader
* decoder_thread: change the fallback decoder name to "mad"
* output_thread: check again if output is open on CANCEL
* update: fixed memory leak during container scan
ver 0.15.4 (2009/10/03)
* decoders:
- vorbis: revert "faster tag scanning with ov_test_callback()"
- faad: skip assertion failure on large ID3 tags
- ffmpeg: use the "artist" tag if "author" is not present
* output:
- osx: fix the OS X 10.6 build
ver 0.15.3 (2009/08/29)
* decoders:
- vorbis: faster tag scanning with ov_test_callback()
......
AC_PREREQ(2.60)
AC_INIT(mpd, 0.15.3, musicpd-dev-team@lists.sourceforge.net)
AC_INIT(mpd, 0.15.5, 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)
......
......@@ -177,11 +177,11 @@ input {
#audio_output {
# type "alsa"
# name "My ALSA Device"
# device "hw:0,0" # optional
# format "44100:16:2" # optional
# mixer_device "default" # optional
# mixer_control "PCM" # optional
# mixer_index "0" # optional
## device "hw:0,0" # optional
## format "44100:16:2" # optional
## mixer_device "default" # optional
## mixer_control "PCM" # optional
## mixer_index "0" # optional
#}
#
# An example of an OSS output:
......@@ -189,10 +189,10 @@ input {
#audio_output {
# type "oss"
# name "My OSS Device"
# device "/dev/dsp" # optional
# format "44100:16:2" # optional
# mixer_device "/dev/mixer" # optional
# mixer_control "PCM" # optional
## device "/dev/dsp" # optional
## format "44100:16:2" # optional
## mixer_device "/dev/mixer" # optional
## mixer_control "PCM" # optional
#}
#
# An example of a shout output (for streaming to Icecast):
......@@ -208,12 +208,12 @@ input {
# quality "5.0"
# bitrate "128"
# format "44100:16:1"
# protocol "icecast2" # optional
# user "source" # optional
# description "My Stream Description" # optional
# genre "jazz" # optional
# public "no" # optional
# timeout "2" # optional
## protocol "icecast2" # optional
## user "source" # optional
## description "My Stream Description" # optional
## genre "jazz" # optional
## public "no" # optional
## timeout "2" # optional
#}
#
# An example of a httpd output (built-in HTTP streaming server):
......@@ -223,7 +223,7 @@ input {
# name "My HTTP Stream"
# encoder "vorbis" # optional, vorbis or lame
# port "8000"
# quality "5.0" # do not define if bitrate is defined
## quality "5.0" # do not define if bitrate is defined
# bitrate "128" # do not define if quality is defined
# format "44100:16:1"
#}
......@@ -233,8 +233,8 @@ input {
#audio_output {
# type "pulse"
# name "My Pulse Output"
# server "remote_server" # optional
# sink "remote_server_sink" # optional
## server "remote_server" # optional
## sink "remote_server_sink" # optional
#}
#
## Example "pipe" output:
......
......@@ -1210,29 +1210,24 @@ OK
<term>
<cmdsynopsis>
<command>update</command>
<arg><replaceable>URI</replaceable></arg>
<arg choice="opt"><replaceable>URI</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Updates the music database.
Updates the music database: find new files, remove
deleted files, update modified files.
</para>
<para>
<varname>URI</varname> is a particular directory or
song/file to update.
song/file to update. If you do not specify it,
everything is updated.
</para>
<para>
Prints "updating_db: JOBID" where
<varname>JOBID</varname> is the job id requested for
your update, and is displayed in status, while the
requested update is happening.
</para>
<para>
To update a number of paths/songs at once, use
command_list, it will be much more faster/efficient.
Also, if you use a command_list for updating, only one
<command>update</command> job id will be returned per
sequence of updates.
<varname>JOBID</varname> is a positive number
identifying the update job. You can read the current
job id in the <command>status</command> response.
</para>
</listitem>
</varlistentry>
......
......@@ -84,6 +84,11 @@ aiff_seek_id3(FILE *file)
return 0;
size = GUINT32_FROM_BE(chunk.size);
if (size > G_MAXINT32)
/* too dangerous, bail out: possible integer
underflow when casting to off_t */
return 0;
if (size % 2 != 0)
/* pad byte */
++size;
......@@ -92,11 +97,6 @@ aiff_seek_id3(FILE *file)
/* found it! */
return size;
if ((off_t)size < 0)
/* integer underflow after cast to signed
type */
return 0;
ret = fseek(file, size, SEEK_CUR);
if (ret != 0)
return 0;
......
......@@ -162,6 +162,7 @@ faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is)
size_t tagsize;
const unsigned char *data;
size_t length;
bool success;
fileread = is->size >= 0 ? is->size : 0;
......@@ -179,8 +180,11 @@ faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is)
tagsize += 10;
decoder_buffer_consume(buffer, tagsize);
decoder_buffer_fill(buffer);
success = decoder_buffer_skip(buffer, tagsize) &&
decoder_buffer_fill(buffer);
if (!success)
return -1;
data = decoder_buffer_read(buffer, &length);
if (data == NULL)
return -1;
......
......@@ -338,13 +338,14 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
}
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
static void
static bool
ffmpeg_copy_metadata(struct tag *tag, AVMetadata *m,
enum tag_type type, const char *name)
{
AVMetadataTag *mt = av_metadata_get(m, name, NULL, 0);
if (mt != NULL)
tag_add_item(tag, type, mt->value);
return mt != NULL;
}
#endif
......@@ -359,7 +360,9 @@ static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx)
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_TITLE, "title");
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_ARTIST, "author");
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_ALBUM, "album");
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_COMMENT, "comment");
ffmpeg_copy_metadata(tag, f->metadata, TAG_ITEM_GENRE, "genre");
......
......@@ -299,10 +299,10 @@ flac_cue_tag_load(const char *file)
unsigned int sample_rate = 0;
FLAC__uint64 track_time = 0;
#ifdef HAVE_CUE /* libcue */
FLAC__StreamMetadata* vc = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
FLAC__StreamMetadata* vc;
#endif /* libcue */
FLAC__StreamMetadata* si = FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO);
FLAC__StreamMetadata* cs = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET);
FLAC__StreamMetadata* cs;
tnum = flac_vtrack_tnum(file);
char_tnum = g_strdup_printf("%u", tnum);
......@@ -326,6 +326,7 @@ flac_cue_tag_load(const char *file)
}
}
}
FLAC__metadata_object_delete(vc);
}
#endif /* libcue */
......
......@@ -383,7 +383,7 @@ vorbis_tag_dup(const char *file)
return NULL;
}
if (ov_test_callbacks(fp, &vf, NULL, 0, OV_CALLBACKS_STREAMONLY) < 0) {
if (ov_open(fp, &vf, NULL, 0) < 0) {
fclose(fp);
return NULL;
}
......
......@@ -138,3 +138,29 @@ decoder_buffer_consume(struct decoder_buffer *buffer, size_t nbytes)
assert(buffer->consumed <= buffer->length);
}
bool
decoder_buffer_skip(struct decoder_buffer *buffer, size_t nbytes)
{
size_t length;
const void *data;
bool success;
/* this could probably be optimized by seeking */
while (true) {
data = decoder_buffer_read(buffer, &length);
if (data != NULL) {
if (length > nbytes)
length = nbytes;
decoder_buffer_consume(buffer, length);
nbytes -= length;
if (nbytes == 0)
return true;
}
success = decoder_buffer_fill(buffer);
if (!success)
return false;
}
}
......@@ -93,4 +93,14 @@ decoder_buffer_read(const struct decoder_buffer *buffer, size_t *length_r);
void
decoder_buffer_consume(struct decoder_buffer *buffer, size_t nbytes);
/**
* Skips the specified number of bytes, discarding its data.
*
* @param buffer the decoder_buffer object
* @param nbytes the number of bytes to skip
* @return true on success, false on error
*/
bool
decoder_buffer_skip(struct decoder_buffer *buffer, size_t nbytes);
#endif
......@@ -169,7 +169,7 @@ static void decoder_run_song(const struct song *song, const char *uri)
if (plugin == NULL) {
/* we already know our mp3Plugin supports streams, no
* need to check for stream{Types,DecodeFunc} */
if ((plugin = decoder_plugin_from_name("mp3"))) {
if ((plugin = decoder_plugin_from_name("mad"))) {
ret = decoder_stream_decode(plugin, &decoder,
&input_stream);
}
......
......@@ -282,6 +282,42 @@ input_curl_select(struct input_curl *c)
return ret;
}
static bool
fill_buffer(struct input_stream *is)
{
struct input_curl *c = is->data;
CURLMcode mcode = CURLM_CALL_MULTI_PERFORM;
while (!c->eof && g_queue_is_empty(c->buffers)) {
int running_handles;
bool bret;
if (mcode != CURLM_CALL_MULTI_PERFORM) {
/* if we're still here, there is no input yet
- wait for input */
int ret = input_curl_select(c);
if (ret <= 0)
/* no data yet or error */
return false;
}
mcode = curl_multi_perform(c->multi, &running_handles);
if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) {
g_warning("curl_multi_perform() failed: %s\n",
curl_multi_strerror(mcode));
c->eof = true;
is->ready = true;
return false;
}
bret = input_curl_multi_info_read(is);
if (!bret)
return false;
}
return !g_queue_is_empty(c->buffers);
}
/**
* Mark a part of the buffer object as consumed.
*/
......@@ -381,7 +417,7 @@ static size_t
input_curl_read(struct input_stream *is, void *ptr, size_t size)
{
struct input_curl *c = is->data;
CURLMcode mcode = CURLM_CALL_MULTI_PERFORM;
bool success;
GQueue *rewind_buffers;
size_t nbytes = 0;
char *dest = ptr;
......@@ -407,54 +443,33 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size)
}
#endif
/* fill the buffer */
while (!c->eof && g_queue_is_empty(c->buffers)) {
int running_handles;
bool bret;
if (mcode != CURLM_CALL_MULTI_PERFORM) {
/* if we're still here, there is no input yet
- wait for input */
int ret = input_curl_select(c);
if (ret <= 0)
/* no data yet or error */
return 0;
}
mcode = curl_multi_perform(c->multi, &running_handles);
if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) {
g_warning("curl_multi_perform() failed: %s\n",
curl_multi_strerror(mcode));
c->eof = true;
is->ready = true;
return 0;
}
do {
/* fill the buffer */
bret = input_curl_multi_info_read(is);
if (!bret)
success = fill_buffer(is);
if (!success)
return 0;
}
/* send buffer contents */
/* send buffer contents */
if (c->rewind != NULL &&
(!g_queue_is_empty(c->rewind) || is->offset == 0))
/* at the beginning or already writing the rewind
buffer list */
rewind_buffers = c->rewind;
else
/* we don't need the rewind buffers anymore */
rewind_buffers = NULL;
if (c->rewind != NULL &&
(!g_queue_is_empty(c->rewind) || is->offset == 0))
/* at the beginning or already writing the rewind
buffer list */
rewind_buffers = c->rewind;
else
/* we don't need the rewind buffers anymore */
rewind_buffers = NULL;
while (size > 0 && !g_queue_is_empty(c->buffers)) {
size_t copy = read_from_buffer(&c->icy_metadata, c->buffers,
dest + nbytes, size,
rewind_buffers);
while (size > 0 && !g_queue_is_empty(c->buffers)) {
size_t copy = read_from_buffer(&c->icy_metadata, c->buffers,
dest + nbytes, size,
rewind_buffers);
nbytes += copy;
size -= copy;
}
nbytes += copy;
size -= copy;
}
} while (nbytes == 0);
if (icy_defined(&c->icy_metadata))
copy_icy_tag(c);
......
......@@ -27,7 +27,7 @@
#include <errno.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "jack"
#define G_LOG_DOMAIN "input_mms"
struct input_mms {
mmsx_t *mms;
......
......@@ -21,6 +21,7 @@
#include <glib.h>
#include <AudioUnit/AudioUnit.h>
#include <CoreServices/CoreServices.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "osx"
......
......@@ -257,7 +257,8 @@ static gpointer audio_output_task(gpointer arg)
case AO_COMMAND_CANCEL:
ao->chunk = NULL;
ao_plugin_cancel(ao->plugin, ao->data);
if (ao->open)
ao_plugin_cancel(ao->plugin, ao->data);
ao_command_finished(ao);
/* the player thread will now clear our music
......
......@@ -83,6 +83,11 @@ riff_seek_id3(FILE *file)
return 0;
size = GUINT32_FROM_LE(chunk.size);
if (size > G_MAXINT32)
/* too dangerous, bail out: possible integer
underflow when casting to off_t */
return 0;
if (size % 2 != 0)
/* pad byte */
++size;
......@@ -91,11 +96,6 @@ riff_seek_id3(FILE *file)
/* found it! */
return size;
if ((off_t)size < 0)
/* integer underflow after cast to signed
type */
return 0;
ret = fseek(file, size, SEEK_CUR);
if (ret != 0)
return 0;
......
......@@ -459,20 +459,20 @@ update_container_file( struct directory* directory,
while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL)
{
struct song* song = song_file_new(vtrack, contdir);
if (song == NULL)
return true;
char *child_path_fs;
// shouldn't be necessary but it's there..
song->mtime = st->st_mtime;
song->tag = plugin->tag_dup(map_directory_child_fs(contdir, vtrack));
child_path_fs = map_directory_child_fs(contdir, vtrack);
g_free(vtrack);
song->tag = plugin->tag_dup(child_path_fs);
g_free(child_path_fs);
songvec_add(&contdir->songs, song);
song = NULL;
modified = true;
g_free(vtrack);
}
g_free(pathname);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment