Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
8c743fd3
Commit
8c743fd3
authored
Oct 24, 2010
by
Alexey Morsov
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'release-0.15.13' into alt
parents
2835998a
b552e9a1
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
510 additions
and
213 deletions
+510
-213
Makefile.am
Makefile.am
+1
-0
NEWS
NEWS
+51
-0
configure.ac
configure.ac
+7
-10
cue_tag.c
src/cue/cue_tag.c
+1
-21
ffmpeg_plugin.c
src/decoder/ffmpeg_plugin.c
+103
-75
mad_plugin.c
src/decoder/mad_plugin.c
+34
-19
mikmod_plugin.c
src/decoder/mikmod_plugin.c
+4
-2
mp4ff_plugin.c
src/decoder/mp4ff_plugin.c
+20
-18
mpcdec_plugin.c
src/decoder/mpcdec_plugin.c
+9
-1
vorbis_plugin.c
src/decoder/vorbis_plugin.c
+12
-7
wildmidi_plugin.c
src/decoder/wildmidi_plugin.c
+4
-0
directory_print.c
src/directory_print.c
+2
-6
directory_print.h
src/directory_print.h
+1
-1
icy_server.c
src/icy_server.c
+1
-0
curl_input_plugin.c
src/input/curl_input_plugin.c
+17
-2
mms_input_plugin.c
src/input/mms_input_plugin.c
+3
-0
rewind_input_plugin.c
src/input/rewind_input_plugin.c
+13
-4
listen.c
src/listen.c
+7
-1
locate.c
src/locate.c
+2
-2
notify.c
src/notify.c
+7
-0
notify.h
src/notify.h
+5
-0
httpd_output_plugin.c
src/output/httpd_output_plugin.c
+1
-1
output_thread.c
src/output_thread.c
+10
-0
pcm_buffer.h
src/pcm_buffer.h
+1
-1
player_thread.c
src/player_thread.c
+27
-0
playlist.c
src/playlist.c
+2
-1
playlist_control.c
src/playlist_control.c
+3
-0
tag.c
src/tag.c
+57
-9
tag.h
src/tag.h
+25
-0
tag_ape.c
src/tag_ape.c
+37
-32
tag_table.h
src/tag_table.h
+43
-0
No files found.
Makefile.am
View file @
8c743fd3
...
@@ -142,6 +142,7 @@ mpd_headers = \
...
@@ -142,6 +142,7 @@ mpd_headers = \
src/tag.h
\
src/tag.h
\
src/tag_internal.h
\
src/tag_internal.h
\
src/tag_pool.h
\
src/tag_pool.h
\
src/tag_table.h
\
src/tag_ape.h
\
src/tag_ape.h
\
src/tag_id3.h
\
src/tag_id3.h
\
src/tag_print.h
\
src/tag_print.h
\
...
...
NEWS
View file @
8c743fd3
ver 0.15.13 (2010/10/10)
* output_thread: fix race condition after CANCEL command
* output:
- httpd: fix random data in stream title
- httpd: MIME type audio/ogg for Ogg Vorbis
* input:
- rewind: update MIME not only once
- rewind: enable for MMS
ver 0.15.12 (2010/07/20)
* input:
- curl: remove assertion after curl_multi_fdset()
* tags:
- rva2: set "gain", not "peak"
* decoders:
- wildmidi: support version 0.2.3
ver 0.15.11 (2010/06/14)
* tags:
- ape: support album artist
* decoders:
- mp4ff: support tags "album artist", "albumartist", "band"
- mikmod: fix memory leak
- vorbis: handle uri==NULL
- ffmpeg: fix memory leak
- ffmpeg: free AVFormatContext on error
- ffmpeg: read more metadata
- ffmpeg: fix libavformat 0.6 by using av_open_input_stream()
* playlist: emit IDLE_OPTIONS when resetting single mode
* listen: make get_remote_uid() work on BSD
ver 0.15.10 (2010/05/30)
* input:
- mms: fix memory leak in error handler
- mms: initialize the "eof" attribute
* decoders:
- mad: properly calculate ID3 size without libid3tag
ver 0.15.9 (2010/03/21)
* decoders:
- mad: fix crash when seeking at end of song
- mpcdec: fix negative shift on fixed-point samples
- mpcdec: fix replay gain formula with v8
* playlist: fix single+repeat in random mode
* player: postpone song tags during cross-fade
ver 0.15.8 (2010/01/17)
ver 0.15.8 (2010/01/17)
* input:
* input:
- curl: allow rewinding with Icy-Metadata
- curl: allow rewinding with Icy-Metadata
...
...
configure.ac
View file @
8c743fd3
AC_PREREQ(2.60)
AC_PREREQ(2.60)
AC_INIT(mpd, 0.15.
8
, musicpd-dev-team@lists.sourceforge.net)
AC_INIT(mpd, 0.15.
13
, musicpd-dev-team@lists.sourceforge.net)
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_SRCDIR([src/main.c])
AM_INIT_AUTOMAKE([foreign 1.9 dist-bzip2])
AM_INIT_AUTOMAKE([foreign 1.9 dist-bzip2])
AM_CONFIG_HEADER(config.h)
AM_CONFIG_HEADER(config.h)
...
@@ -177,6 +177,7 @@ AC_ARG_ENABLE(un,
...
@@ -177,6 +177,7 @@ AC_ARG_ENABLE(un,
if test x$enable_un = xyes; then
if test x$enable_un = xyes; then
AC_DEFINE(HAVE_UN, 1, [Define if unix domain socket support is enabled])
AC_DEFINE(HAVE_UN, 1, [Define if unix domain socket support is enabled])
STRUCT_UCRED
STRUCT_UCRED
AC_CHECK_FUNCS(getpeereid)
fi
fi
...
@@ -913,18 +914,10 @@ fi
...
@@ -913,18 +914,10 @@ fi
AM_CONDITIONAL(HAVE_AUDIOFILE, test x$enable_audiofile = xyes)
AM_CONDITIONAL(HAVE_AUDIOFILE, test x$enable_audiofile = xyes)
MPD_AUTO_PKG(ffmpeg, FFMPEG, [libavformat
libavcodec libavutil
],
MPD_AUTO_PKG(ffmpeg, FFMPEG, [libavformat
>= 52 libavcodec >= 51 libavutil >= 49
],
[ffmpeg decoder library], [libavformat+libavcodec+libavutil not found])
[ffmpeg decoder library], [libavformat+libavcodec+libavutil not found])
if test x$enable_ffmpeg = xyes; then
if test x$enable_ffmpeg = xyes; then
old_LIBS=$LIBS
LIBS="$LIBS $FFMPEG_LIBS"
AC_CHECK_LIB(avcodec, avcodec_decode_audio2,,
enable_ffmpeg=no)
LIBS=$old_LIBS
fi
if test x$enable_ffmpeg = xyes; then
# prior to ffmpeg svn12865, you had to specify include files
# prior to ffmpeg svn12865, you had to specify include files
# without path prefix
# without path prefix
old_CPPCFLAGS=$CPPFLAGS
old_CPPCFLAGS=$CPPFLAGS
...
@@ -957,6 +950,10 @@ if test x$enable_wildmidi = xyes; then
...
@@ -957,6 +950,10 @@ if test x$enable_wildmidi = xyes; then
AC_CHECK_LIB(WildMidi, WildMidi_Init,,
AC_CHECK_LIB(WildMidi, WildMidi_Init,,
AC_MSG_ERROR([libwildmidi not found]))
AC_MSG_ERROR([libwildmidi not found]))
AC_CHECK_LIB(WildMidi, WildMidi_SampledSeek,
[AC_DEFINE(HAVE_WILDMIDI_SAMPLED_SEEK, 1,
[Defined if WildMidi_SampledSeek() is available (libwildmidi <= 0.2.2)])])
CFLAGS=$oldcflags
CFLAGS=$oldcflags
LIBS=$oldlibs
LIBS=$oldlibs
CPPFLAGS=$oldcppflags
CPPFLAGS=$oldcppflags
...
...
src/cue/cue_tag.c
View file @
8c743fd3
...
@@ -173,7 +173,6 @@ cue_tag_file( FILE* fp,
...
@@ -173,7 +173,6 @@ cue_tag_file( FILE* fp,
{
{
struct
tag
*
cd_tag
=
NULL
;
struct
tag
*
cd_tag
=
NULL
;
struct
tag
*
track_tag
=
NULL
;
struct
tag
*
track_tag
=
NULL
;
struct
tag
*
merge_tag
=
NULL
;
struct
Cd
*
cd
=
NULL
;
struct
Cd
*
cd
=
NULL
;
if
(
tnum
>
256
)
if
(
tnum
>
256
)
...
@@ -199,26 +198,7 @@ cue_tag_file( FILE* fp,
...
@@ -199,26 +198,7 @@ cue_tag_file( FILE* fp,
cd_delete
(
cd
);
cd_delete
(
cd
);
}
}
if
((
cd_tag
!=
NULL
)
&&
(
track_tag
!=
NULL
))
return
tag_merge_replace
(
cd_tag
,
track_tag
);
{
merge_tag
=
tag_merge
(
cd_tag
,
track_tag
);
tag_free
(
cd_tag
);
tag_free
(
track_tag
);
return
merge_tag
;
}
else
if
(
cd_tag
!=
NULL
)
{
return
cd_tag
;
}
else
if
(
track_tag
!=
NULL
)
{
return
track_tag
;
}
else
return
NULL
;
}
}
struct
tag
*
struct
tag
*
...
...
src/decoder/ffmpeg_plugin.c
View file @
8c743fd3
...
@@ -53,48 +53,27 @@ struct ffmpeg_context {
...
@@ -53,48 +53,27 @@ struct ffmpeg_context {
struct
tag
*
tag
;
struct
tag
*
tag
;
};
};
struct
ffmpeg_stream
{
struct
mpd_ffmpeg_stream
{
/** hack - see url_to_struct() */
char
url
[
64
];
struct
decoder
*
decoder
;
struct
decoder
*
decoder
;
struct
input_stream
*
input
;
struct
input_stream
*
input
;
};
/**
ByteIOContext
*
io
;
* Convert a faked mpd:// URL to a ffmpeg_stream structure. This is a
unsigned
char
buffer
[
8192
];
* hack because ffmpeg does not provide a nice API for passing a
};
* user-defined pointer to mpdurl_open().
*/
static
struct
ffmpeg_stream
*
url_to_struct
(
const
char
*
url
)
{
union
{
const
char
*
in
;
struct
ffmpeg_stream
*
out
;
}
u
=
{
.
in
=
url
};
return
u
.
out
;
}
static
int
mpd_ffmpeg_open
(
URLContext
*
h
,
const
char
*
filename
,
G_GNUC_UNUSED
int
flags
)
{
struct
ffmpeg_stream
*
stream
=
url_to_struct
(
filename
);
h
->
priv_data
=
stream
;
h
->
is_streamed
=
stream
->
input
->
seekable
?
0
:
1
;
return
0
;
}
static
int
mpd_ffmpeg_read
(
URLContext
*
h
,
unsigned
char
*
buf
,
int
size
)
static
int
mpd_ffmpeg_stream_read
(
void
*
opaque
,
uint8_t
*
buf
,
int
size
)
{
{
struct
ffmpeg_stream
*
stream
=
(
struct
ffmpeg_stream
*
)
h
->
priv_data
;
struct
mpd_ffmpeg_stream
*
stream
=
opaque
;
return
decoder_read
(
stream
->
decoder
,
stream
->
input
,
return
decoder_read
(
stream
->
decoder
,
stream
->
input
,
(
void
*
)
buf
,
size
);
(
void
*
)
buf
,
size
);
}
}
static
int64_t
mpd_ffmpeg_seek
(
URLContext
*
h
,
int64_t
pos
,
int
whence
)
static
int64_t
mpd_ffmpeg_stream_seek
(
void
*
opaque
,
int64_t
pos
,
int
whence
)
{
{
struct
ffmpeg_stream
*
stream
=
(
struct
ffmpeg_stream
*
)
h
->
priv_data
;
struct
mpd_ffmpeg_stream
*
stream
=
opaque
;
bool
ret
;
bool
ret
;
if
(
whence
==
AVSEEK_SIZE
)
if
(
whence
==
AVSEEK_SIZE
)
...
@@ -107,25 +86,36 @@ static int64_t mpd_ffmpeg_seek(URLContext *h, int64_t pos, int whence)
...
@@ -107,25 +86,36 @@ static int64_t mpd_ffmpeg_seek(URLContext *h, int64_t pos, int whence)
return
stream
->
input
->
offset
;
return
stream
->
input
->
offset
;
}
}
static
int
mpd_ffmpeg_close
(
URLContext
*
h
)
static
struct
mpd_ffmpeg_stream
*
mpd_ffmpeg_stream_open
(
struct
decoder
*
decoder
,
struct
input_stream
*
input
)
{
{
h
->
priv_data
=
NULL
;
struct
mpd_ffmpeg_stream
*
stream
=
g_new
(
struct
mpd_ffmpeg_stream
,
1
);
return
0
;
stream
->
decoder
=
decoder
;
stream
->
input
=
input
;
stream
->
io
=
av_alloc_put_byte
(
stream
->
buffer
,
sizeof
(
stream
->
buffer
),
false
,
stream
,
mpd_ffmpeg_stream_read
,
NULL
,
input
->
seekable
?
mpd_ffmpeg_stream_seek
:
NULL
);
if
(
stream
->
io
==
NULL
)
{
g_free
(
stream
);
return
NULL
;
}
return
stream
;
}
}
static
URLProtocol
mpd_ffmpeg_fileops
=
{
static
void
.
name
=
"mpd"
,
mpd_ffmpeg_stream_close
(
struct
mpd_ffmpeg_stream
*
stream
)
.
url_open
=
mpd_ffmpeg_open
,
{
.
url_read
=
mpd_ffmpeg_read
,
av_free
(
stream
->
io
);
.
url_seek
=
mpd_ffmpeg_seek
,
g_free
(
stream
);
.
url_close
=
mpd_ffmpeg_close
,
}
};
static
bool
static
bool
ffmpeg_init
(
G_GNUC_UNUSED
const
struct
config_param
*
param
)
ffmpeg_init
(
G_GNUC_UNUSED
const
struct
config_param
*
param
)
{
{
av_register_all
();
av_register_all
();
register_protocol
(
&
mpd_ffmpeg_fileops
);
return
true
;
return
true
;
}
}
...
@@ -140,64 +130,86 @@ ffmpeg_find_audio_stream(const AVFormatContext *format_context)
...
@@ -140,64 +130,86 @@ ffmpeg_find_audio_stream(const AVFormatContext *format_context)
return
-
1
;
return
-
1
;
}
}
/**
static
AVInputFormat
*
* Append the suffix of the original URI to the virtual stream URI.
ffmpeg_probe
(
struct
decoder
*
decoder
,
struct
input_stream
*
is
,
* Without this, libavformat cannot detect some of the codecs
const
char
*
uri
)
* (e.g. "shorten").
*/
static
void
append_uri_suffix
(
struct
ffmpeg_stream
*
stream
,
const
char
*
uri
)
{
{
assert
(
stream
!=
NULL
);
enum
{
assert
(
uri
!=
NULL
);
BUFFER_SIZE
=
16384
,
PADDING
=
16
,
};
unsigned
char
*
buffer
=
g_malloc
(
BUFFER_SIZE
);
size_t
nbytes
=
decoder_read
(
decoder
,
is
,
buffer
,
BUFFER_SIZE
);
if
(
nbytes
<=
PADDING
||
!
input_stream_seek
(
is
,
0
,
SEEK_SET
))
{
g_free
(
buffer
);
return
NULL
;
}
/* some ffmpeg parsers (e.g. ac3_parser.c) read a few bytes
beyond the declared buffer limit, which makes valgrind
angry; this workaround removes some padding from the buffer
size */
nbytes
-=
PADDING
;
char
*
base
=
g_path_get_basename
(
uri
);
AVProbeData
avpd
=
{
.
buf
=
buffer
,
.
buf_size
=
nbytes
,
.
filename
=
uri
,
};
const
char
*
suffix
=
strrchr
(
base
,
'.'
);
AVInputFormat
*
format
=
av_probe_input_format
(
&
avpd
,
true
);
if
(
suffix
!=
NULL
&&
suffix
[
1
]
!=
0
)
g_free
(
buffer
);
g_strlcat
(
stream
->
url
,
suffix
,
sizeof
(
stream
->
url
));
g_free
(
base
)
;
return
format
;
}
}
static
bool
static
bool
ffmpeg_helper
(
const
char
*
uri
,
struct
input_stream
*
input
,
ffmpeg_helper
(
const
char
*
uri
,
struct
decoder
*
decoder
,
struct
input_stream
*
input
,
bool
(
*
callback
)(
struct
ffmpeg_context
*
ctx
),
bool
(
*
callback
)(
struct
ffmpeg_context
*
ctx
),
struct
ffmpeg_context
*
ctx
)
struct
ffmpeg_context
*
ctx
)
{
{
AVInputFormat
*
input_format
=
ffmpeg_probe
(
decoder
,
input
,
uri
);
if
(
input_format
==
NULL
)
return
false
;
g_debug
(
"detected input format '%s' (%s)"
,
input_format
->
name
,
input_format
->
long_name
);
struct
mpd_ffmpeg_stream
*
stream
=
mpd_ffmpeg_stream_open
(
decoder
,
input
);
if
(
stream
==
NULL
)
{
g_warning
(
"Failed to open stream"
);
return
false
;
}
AVFormatContext
*
format_context
;
AVFormatContext
*
format_context
;
AVCodecContext
*
codec_context
;
AVCodecContext
*
codec_context
;
AVCodec
*
codec
;
AVCodec
*
codec
;
int
audio_stream
;
int
audio_stream
;
struct
ffmpeg_stream
stream
=
{
.
url
=
"mpd://X"
,
/* only the mpd:// prefix matters */
};
bool
ret
;
bool
ret
;
if
(
uri
!=
NULL
)
append_uri_suffix
(
&
stream
,
uri
);
stream
.
input
=
input
;
if
(
ctx
&&
ctx
->
decoder
)
{
stream
.
decoder
=
ctx
->
decoder
;
//are we in decoding loop ?
}
else
{
stream
.
decoder
=
NULL
;
}
//ffmpeg works with ours "fileops" helper
//ffmpeg works with ours "fileops" helper
if
(
av_open_input_file
(
&
format_context
,
stream
.
url
,
NULL
,
0
,
NULL
)
!=
0
)
{
if
(
av_open_input_stream
(
&
format_context
,
stream
->
io
,
uri
,
input_format
,
NULL
)
!=
0
)
{
g_warning
(
"Open failed
\n
"
);
g_warning
(
"Open failed
\n
"
);
mpd_ffmpeg_stream_close
(
stream
);
return
false
;
return
false
;
}
}
if
(
av_find_stream_info
(
format_context
)
<
0
)
{
if
(
av_find_stream_info
(
format_context
)
<
0
)
{
g_warning
(
"Couldn't find stream info
\n
"
);
g_warning
(
"Couldn't find stream info
\n
"
);
av_close_input_stream
(
format_context
);
mpd_ffmpeg_stream_close
(
stream
);
return
false
;
return
false
;
}
}
audio_stream
=
ffmpeg_find_audio_stream
(
format_context
);
audio_stream
=
ffmpeg_find_audio_stream
(
format_context
);
if
(
audio_stream
==
-
1
)
{
if
(
audio_stream
==
-
1
)
{
g_warning
(
"No audio stream inside
\n
"
);
g_warning
(
"No audio stream inside
\n
"
);
av_close_input_stream
(
format_context
);
mpd_ffmpeg_stream_close
(
stream
);
return
false
;
return
false
;
}
}
...
@@ -209,11 +221,15 @@ ffmpeg_helper(const char *uri, struct input_stream *input,
...
@@ -209,11 +221,15 @@ ffmpeg_helper(const char *uri, struct input_stream *input,
if
(
!
codec
)
{
if
(
!
codec
)
{
g_warning
(
"Unsupported audio codec
\n
"
);
g_warning
(
"Unsupported audio codec
\n
"
);
av_close_input_stream
(
format_context
);
mpd_ffmpeg_stream_close
(
stream
);
return
false
;
return
false
;
}
}
if
(
avcodec_open
(
codec_context
,
codec
)
<
0
)
{
if
(
avcodec_open
(
codec_context
,
codec
)
<
0
)
{
g_warning
(
"Could not open codec
\n
"
);
g_warning
(
"Could not open codec
\n
"
);
av_close_input_stream
(
format_context
);
mpd_ffmpeg_stream_close
(
stream
);
return
false
;
return
false
;
}
}
...
@@ -227,7 +243,8 @@ ffmpeg_helper(const char *uri, struct input_stream *input,
...
@@ -227,7 +243,8 @@ ffmpeg_helper(const char *uri, struct input_stream *input,
ret
=
true
;
ret
=
true
;
avcodec_close
(
codec_context
);
avcodec_close
(
codec_context
);
av_close_input_file
(
format_context
);
av_close_input_stream
(
format_context
);
mpd_ffmpeg_stream_close
(
stream
);
return
ret
;
return
ret
;
}
}
...
@@ -372,8 +389,10 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
...
@@ -372,8 +389,10 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
ctx
.
input
=
input
;
ctx
.
input
=
input
;
ctx
.
decoder
=
decoder
;
ctx
.
decoder
=
decoder
;
ffmpeg_helper
(
decoder_get_uri
(
decoder
),
input
,
char
*
uri
=
decoder_get_uri
(
decoder
);
ffmpeg_helper
(
uri
,
decoder
,
input
,
ffmpeg_decode_internal
,
&
ctx
);
ffmpeg_decode_internal
,
&
ctx
);
g_free
(
uri
);
}
}
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
...
@@ -401,12 +420,21 @@ static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx)
...
@@ -401,12 +420,21 @@ static bool ffmpeg_tag_internal(struct ffmpeg_context *ctx)
av_metadata_conv
(
f
,
NULL
,
f
->
iformat
->
metadata_conv
);
av_metadata_conv
(
f
,
NULL
,
f
->
iformat
->
metadata_conv
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_TITLE
,
"title"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_TITLE
,
"title"
);
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(50<<8))
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_ARTIST
,
"artist"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_DATE
,
"date"
);
#else
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_ARTIST
,
"author"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_ARTIST
,
"author"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_DATE
,
"year"
);
#endif
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_ALBUM
,
"album"
);
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_COMMENT
,
"comment"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_GENRE
,
"genre"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_GENRE
,
"genre"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_TRACK
,
"track"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_TRACK
,
"track"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_DATE
,
"year"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_ALBUM_ARTIST
,
"album_artist"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_COMPOSER
,
"composer"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_PERFORMER
,
"performer"
);
ffmpeg_copy_metadata
(
tag
,
f
->
metadata
,
TAG_ITEM_DISC
,
"disc"
);
#else
#else
if
(
f
->
author
[
0
])
if
(
f
->
author
[
0
])
tag_add_item
(
tag
,
TAG_ITEM_ARTIST
,
f
->
author
);
tag_add_item
(
tag
,
TAG_ITEM_ARTIST
,
f
->
author
);
...
@@ -450,7 +478,7 @@ static struct tag *ffmpeg_tag(const char *file)
...
@@ -450,7 +478,7 @@ static struct tag *ffmpeg_tag(const char *file)
ctx
.
decoder
=
NULL
;
ctx
.
decoder
=
NULL
;
ctx
.
tag
=
tag_new
();
ctx
.
tag
=
tag_new
();
ret
=
ffmpeg_helper
(
file
,
&
input
,
ffmpeg_tag_internal
,
&
ctx
);
ret
=
ffmpeg_helper
(
file
,
NULL
,
&
input
,
ffmpeg_tag_internal
,
&
ctx
);
if
(
!
ret
)
{
if
(
!
ret
)
{
tag_free
(
ctx
.
tag
);
tag_free
(
ctx
.
tag
);
ctx
.
tag
=
NULL
;
ctx
.
tag
=
NULL
;
...
...
src/decoder/mad_plugin.c
View file @
8c743fd3
...
@@ -209,14 +209,14 @@ mp3_fill_buffer(struct mp3_data *data)
...
@@ -209,14 +209,14 @@ mp3_fill_buffer(struct mp3_data *data)
#ifdef HAVE_ID3TAG
#ifdef HAVE_ID3TAG
/* Parse mp3 RVA2 frame. Shamelessly stolen from madplay. */
/* Parse mp3 RVA2 frame. Shamelessly stolen from madplay. */
static
int
parse_rva2
(
struct
id3_tag
*
tag
,
struct
replay_gain_info
*
replay_gain_info
)
static
bool
parse_rva2
(
struct
id3_tag
*
tag
,
struct
replay_gain_info
*
replay_gain_info
)
{
{
struct
id3_frame
const
*
frame
;
struct
id3_frame
const
*
frame
;
id3_latin1_t
const
*
id
;
id3_latin1_t
const
*
id
;
id3_byte_t
const
*
data
;
id3_byte_t
const
*
data
;
id3_length_t
length
;
id3_length_t
length
;
int
found
;
enum
{
enum
{
CHANNEL_OTHER
=
0x00
,
CHANNEL_OTHER
=
0x00
,
...
@@ -230,18 +230,18 @@ static int parse_rva2(struct id3_tag * tag, struct replay_gain_info * replay_gai
...
@@ -230,18 +230,18 @@ static int parse_rva2(struct id3_tag * tag, struct replay_gain_info * replay_gai
CHANNEL_SUBWOOFER
=
0x08
CHANNEL_SUBWOOFER
=
0x08
};
};
found
=
0
;
/* relative volume adjustment information */
/* relative volume adjustment information */
frame
=
id3_tag_findframe
(
tag
,
"RVA2"
,
0
);
frame
=
id3_tag_findframe
(
tag
,
"RVA2"
,
0
);
if
(
!
frame
)
return
0
;
if
(
frame
==
NULL
)
return
false
;
id
=
id3_field_getlatin1
(
id3_frame_field
(
frame
,
0
));
id
=
id3_field_getlatin1
(
id3_frame_field
(
frame
,
0
));
data
=
id3_field_getbinarydata
(
id3_frame_field
(
frame
,
1
),
data
=
id3_field_getbinarydata
(
id3_frame_field
(
frame
,
1
),
&
length
);
&
length
);
if
(
!
id
||
!
data
)
return
0
;
if
(
id
==
NULL
||
data
==
NULL
)
return
false
;
/*
/*
* "The 'identification' string is used to identify the
* "The 'identification' string is used to identify the
...
@@ -277,22 +277,21 @@ static int parse_rva2(struct id3_tag * tag, struct replay_gain_info * replay_gai
...
@@ -277,22 +277,21 @@ static int parse_rva2(struct id3_tag * tag, struct replay_gain_info * replay_gai
voladj_float
=
(
double
)
voladj_fixed
/
512
;
voladj_float
=
(
double
)
voladj_fixed
/
512
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
peak
=
voladj_float
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
gain
=
voladj_float
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
peak
=
voladj_float
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
gain
=
voladj_float
;
g_debug
(
"parseRVA2: Relative Volume "
g_debug
(
"parseRVA2: Relative Volume "
"%+.1f dB adjustment (%s)
\n
"
,
"%+.1f dB adjustment (%s)
\n
"
,
voladj_float
,
id
);
voladj_float
,
id
);
found
=
1
;
return
true
;
break
;
}
}
data
+=
4
+
peak_bytes
;
data
+=
4
+
peak_bytes
;
length
-=
4
+
peak_bytes
;
length
-=
4
+
peak_bytes
;
}
}
return
f
ound
;
return
f
alse
;
}
}
#endif
#endif
...
@@ -425,7 +424,27 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
...
@@ -425,7 +424,27 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
/* This code is enabled when libid3tag is disabled. Instead
/* This code is enabled when libid3tag is disabled. Instead
of parsing the ID3 frame, it just skips it. */
of parsing the ID3 frame, it just skips it. */
size_t
count
=
data
->
stream
.
bufend
-
data
->
stream
.
this_frame
;
if
(
tagsize
<=
count
)
{
mad_stream_skip
(
&
data
->
stream
,
tagsize
);
mad_stream_skip
(
&
data
->
stream
,
tagsize
);
}
else
{
mad_stream_skip
(
&
data
->
stream
,
count
);
while
(
count
<
tagsize
)
{
size_t
len
=
tagsize
-
count
;
char
ignored
[
1024
];
if
(
len
>
sizeof
(
ignored
))
len
=
sizeof
(
ignored
);
len
=
decoder_read
(
data
->
decoder
,
data
->
input_stream
,
ignored
,
len
);
if
(
len
==
0
)
break
;
else
count
+=
len
;
}
}
#endif
#endif
}
}
...
@@ -433,16 +452,16 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
...
@@ -433,16 +452,16 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
/**
/**
* This function emulates libid3tag when it is disabled. Instead of
* This function emulates libid3tag when it is disabled. Instead of
* doing a real analyzation of the frame, it just checks whether the
* doing a real analyzation of the frame, it just checks whether the
* frame begins with the string "ID3". If so, it returns the
full
* frame begins with the string "ID3". If so, it returns the
length
*
length
.
*
of the ID3 frame
.
*/
*/
static
signed
long
static
signed
long
id3_tag_query
(
const
void
*
p0
,
size_t
length
)
id3_tag_query
(
const
void
*
p0
,
size_t
length
)
{
{
const
char
*
p
=
p0
;
const
char
*
p
=
p0
;
return
length
>
3
&&
memcmp
(
p
,
"ID3"
,
3
)
==
0
return
length
>
=
10
&&
memcmp
(
p
,
"ID3"
,
3
)
==
0
?
length
?
(
p
[
8
]
<<
7
)
+
p
[
9
]
+
10
:
0
;
:
0
;
}
}
#endif
/* !HAVE_ID3TAG */
#endif
/* !HAVE_ID3TAG */
...
@@ -1207,10 +1226,6 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
...
@@ -1207,10 +1226,6 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
if
(
replay_gain_info
)
if
(
replay_gain_info
)
replay_gain_info_free
(
replay_gain_info
);
replay_gain_info_free
(
replay_gain_info
);
if
(
decoder_get_command
(
decoder
)
==
DECODE_COMMAND_SEEK
&&
data
.
mute_frame
==
MUTEFRAME_SEEK
)
decoder_command_finished
(
decoder
);
mp3_data_finish
(
&
data
);
mp3_data_finish
(
&
data
);
}
}
...
...
src/decoder/mikmod_plugin.c
View file @
8c743fd3
...
@@ -219,10 +219,12 @@ static struct tag *modTagDup(const char *file)
...
@@ -219,10 +219,12 @@ static struct tag *modTagDup(const char *file)
ret
->
time
=
0
;
ret
->
time
=
0
;
path2
=
g_strdup
(
file
);
path2
=
g_strdup
(
file
);
title
=
g_strdup
(
Player_LoadTitle
(
path2
)
);
title
=
Player_LoadTitle
(
path2
);
g_free
(
path2
);
g_free
(
path2
);
if
(
title
)
if
(
title
)
{
tag_add_item
(
ret
,
TAG_ITEM_TITLE
,
title
);
tag_add_item
(
ret
,
TAG_ITEM_TITLE
,
title
);
free
(
title
);
}
return
ret
;
return
ret
;
}
}
...
...
src/decoder/mp4ff_plugin.c
View file @
8c743fd3
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
#include "../decoder_api.h"
#include "../decoder_api.h"
#include "config.h"
#include "config.h"
#include "tag_table.h"
#include <glib.h>
#include <glib.h>
...
@@ -339,6 +340,22 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
...
@@ -339,6 +340,22 @@ mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
mp4ff_close
(
mp4fh
);
mp4ff_close
(
mp4fh
);
}
}
static
const
char
*
const
mp4ff_tag_names
[
TAG_NUM_OF_ITEM_TYPES
]
=
{
[
TAG_ITEM_ALBUM_ARTIST
]
=
"album artist"
,
[
TAG_ITEM_COMPOSER
]
=
"writer"
,
[
TAG_ITEM_PERFORMER
]
=
"band"
,
};
static
enum
tag_type
mp4ff_tag_name_parse
(
const
char
*
name
)
{
enum
tag_type
type
=
tag_table_lookup
(
mp4ff_tag_names
,
name
);
if
(
type
==
TAG_NUM_OF_ITEM_TYPES
)
type
=
tag_name_parse_i
(
name
);
return
type
;
}
static
struct
tag
*
static
struct
tag
*
mp4_tag_dup
(
const
char
*
file
)
mp4_tag_dup
(
const
char
*
file
)
{
{
...
@@ -394,24 +411,9 @@ mp4_tag_dup(const char *file)
...
@@ -394,24 +411,9 @@ mp4_tag_dup(const char *file)
mp4ff_meta_get_by_index
(
mp4fh
,
i
,
&
item
,
&
value
);
mp4ff_meta_get_by_index
(
mp4fh
,
i
,
&
item
,
&
value
);
if
(
0
==
g_ascii_strcasecmp
(
"artist"
,
item
))
{
enum
tag_type
type
=
mp4ff_tag_name_parse
(
item
);
tag_add_item
(
ret
,
TAG_ITEM_ARTIST
,
value
);
if
(
type
!=
TAG_NUM_OF_ITEM_TYPES
)
}
else
if
(
0
==
g_ascii_strcasecmp
(
"title"
,
item
))
{
tag_add_item
(
ret
,
type
,
value
);
tag_add_item
(
ret
,
TAG_ITEM_TITLE
,
value
);
}
else
if
(
0
==
g_ascii_strcasecmp
(
"album"
,
item
))
{
tag_add_item
(
ret
,
TAG_ITEM_ALBUM
,
value
);
}
else
if
(
0
==
g_ascii_strcasecmp
(
"track"
,
item
))
{
tag_add_item
(
ret
,
TAG_ITEM_TRACK
,
value
);
}
else
if
(
0
==
g_ascii_strcasecmp
(
"disc"
,
item
))
{
/* Is that the correct id? */
tag_add_item
(
ret
,
TAG_ITEM_DISC
,
value
);
}
else
if
(
0
==
g_ascii_strcasecmp
(
"genre"
,
item
))
{
tag_add_item
(
ret
,
TAG_ITEM_GENRE
,
value
);
}
else
if
(
0
==
g_ascii_strcasecmp
(
"date"
,
item
))
{
tag_add_item
(
ret
,
TAG_ITEM_DATE
,
value
);
}
else
if
(
0
==
g_ascii_strcasecmp
(
"writer"
,
item
))
{
tag_add_item
(
ret
,
TAG_ITEM_COMPOSER
,
value
);
}
free
(
item
);
free
(
item
);
free
(
value
);
free
(
value
);
...
...
src/decoder/mpcdec_plugin.c
View file @
8c743fd3
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include <mpcdec/mpcdec.h>
#include <mpcdec/mpcdec.h>
#else
#else
#include <mpc/mpcdec.h>
#include <mpc/mpcdec.h>
#include <math.h>
#endif
#endif
#include <glib.h>
#include <glib.h>
...
@@ -103,7 +104,7 @@ mpc_to_mpd_sample(MPC_SAMPLE_FORMAT sample)
...
@@ -103,7 +104,7 @@ mpc_to_mpd_sample(MPC_SAMPLE_FORMAT sample)
const
int
shift
=
bits
-
MPC_FIXED_POINT_SCALE_SHIFT
;
const
int
shift
=
bits
-
MPC_FIXED_POINT_SCALE_SHIFT
;
if
(
shift
<
0
)
if
(
shift
<
0
)
val
=
sample
<<
-
shift
;
val
=
sample
>>
-
shift
;
else
else
val
=
sample
<<
shift
;
val
=
sample
<<
shift
;
#else
#else
...
@@ -209,10 +210,17 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
...
@@ -209,10 +210,17 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
}
}
replay_gain_info
=
replay_gain_info_new
();
replay_gain_info
=
replay_gain_info_new
();
#ifdef MPC_IS_OLD_API
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
gain
=
info
.
gain_album
*
0
.
01
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
gain
=
info
.
gain_album
*
0
.
01
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
peak
=
info
.
peak_album
/
32767
.
0
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
peak
=
info
.
peak_album
/
32767
.
0
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
gain
=
info
.
gain_title
*
0
.
01
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
gain
=
info
.
gain_title
*
0
.
01
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
peak
=
info
.
peak_title
/
32767
.
0
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
peak
=
info
.
peak_title
/
32767
.
0
;
#else
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
gain
=
MPC_OLD_GAIN_REF
-
(
info
.
gain_album
/
256
.);
replay_gain_info
->
tuples
[
REPLAY_GAIN_ALBUM
].
peak
=
pow
(
10
,
info
.
peak_album
/
256
.
/
20
)
/
32767
;
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
gain
=
MPC_OLD_GAIN_REF
-
(
info
.
gain_title
/
256
.);
replay_gain_info
->
tuples
[
REPLAY_GAIN_TRACK
].
peak
=
pow
(
10
,
info
.
peak_title
/
256
.
/
20
)
/
32767
;
#endif
decoder_initialized
(
mpd_decoder
,
&
audio_format
,
decoder_initialized
(
mpd_decoder
,
&
audio_format
,
is
->
seekable
,
is
->
seekable
,
...
...
src/decoder/vorbis_plugin.c
View file @
8c743fd3
...
@@ -97,6 +97,13 @@ static long ogg_tell_cb(void *vdata)
...
@@ -97,6 +97,13 @@ static long ogg_tell_cb(void *vdata)
return
(
long
)
data
->
input_stream
->
offset
;
return
(
long
)
data
->
input_stream
->
offset
;
}
}
static
const
ov_callbacks
vorbis_is_callbacks
=
{
.
read_func
=
ogg_read_cb
,
.
seek_func
=
ogg_seek_cb
,
.
close_func
=
ogg_close_cb
,
.
tell_func
=
ogg_tell_cb
,
};
static
const
char
*
static
const
char
*
vorbis_comment_value
(
const
char
*
comment
,
const
char
*
needle
)
vorbis_comment_value
(
const
char
*
comment
,
const
char
*
needle
)
{
{
...
@@ -226,6 +233,9 @@ oggvorbis_seekable(struct decoder *decoder)
...
@@ -226,6 +233,9 @@ oggvorbis_seekable(struct decoder *decoder)
bool
seekable
;
bool
seekable
;
uri
=
decoder_get_uri
(
decoder
);
uri
=
decoder_get_uri
(
decoder
);
if
(
uri
==
NULL
)
return
false
;
/* disable seeking on remote streams, because libvorbis seeks
/* disable seeking on remote streams, because libvorbis seeks
around like crazy, and due to being very expensive, this
around like crazy, and due to being very expensive, this
delays song playback my 10 or 20 seconds */
delays song playback my 10 or 20 seconds */
...
@@ -241,7 +251,6 @@ vorbis_stream_decode(struct decoder *decoder,
...
@@ -241,7 +251,6 @@ vorbis_stream_decode(struct decoder *decoder,
struct
input_stream
*
input_stream
)
struct
input_stream
*
input_stream
)
{
{
OggVorbis_File
vf
;
OggVorbis_File
vf
;
ov_callbacks
callbacks
;
OggCallbackData
data
;
OggCallbackData
data
;
struct
audio_format
audio_format
;
struct
audio_format
audio_format
;
int
current_section
;
int
current_section
;
...
@@ -266,13 +275,9 @@ vorbis_stream_decode(struct decoder *decoder,
...
@@ -266,13 +275,9 @@ vorbis_stream_decode(struct decoder *decoder,
data
.
input_stream
=
input_stream
;
data
.
input_stream
=
input_stream
;
data
.
seekable
=
input_stream
->
seekable
&&
oggvorbis_seekable
(
decoder
);
data
.
seekable
=
input_stream
->
seekable
&&
oggvorbis_seekable
(
decoder
);
callbacks
.
read_func
=
ogg_read_cb
;
if
((
ret
=
ov_open_callbacks
(
&
data
,
&
vf
,
NULL
,
0
,
callbacks
.
seek_func
=
ogg_seek_cb
;
vorbis_is_callbacks
))
<
0
)
{
callbacks
.
close_func
=
ogg_close_cb
;
callbacks
.
tell_func
=
ogg_tell_cb
;
if
((
ret
=
ov_open_callbacks
(
&
data
,
&
vf
,
NULL
,
0
,
callbacks
))
<
0
)
{
const
char
*
error
;
const
char
*
error
;
if
(
decoder_get_command
(
decoder
)
!=
DECODE_COMMAND_NONE
)
if
(
decoder_get_command
(
decoder
)
!=
DECODE_COMMAND_NONE
)
return
;
return
;
...
...
src/decoder/wildmidi_plugin.c
View file @
8c743fd3
...
@@ -99,7 +99,11 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs)
...
@@ -99,7 +99,11 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs)
unsigned
long
seek_where
=
WILDMIDI_SAMPLE_RATE
*
unsigned
long
seek_where
=
WILDMIDI_SAMPLE_RATE
*
decoder_seek_where
(
decoder
);
decoder_seek_where
(
decoder
);
#ifdef HAVE_WILDMIDI_SAMPLED_SEEK
WildMidi_SampledSeek
(
wm
,
&
seek_where
);
WildMidi_SampledSeek
(
wm
,
&
seek_where
);
#else
WildMidi_FastSeek
(
wm
,
&
seek_where
);
#endif
decoder_command_finished
(
decoder
);
decoder_command_finished
(
decoder
);
cmd
=
DECODE_COMMAND_NONE
;
cmd
=
DECODE_COMMAND_NONE
;
}
}
...
...
src/directory_print.c
View file @
8c743fd3
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
#include "client.h"
#include "client.h"
#include "song_print.h"
#include "song_print.h"
static
int
static
void
dirvec_print
(
struct
client
*
client
,
const
struct
dirvec
*
dv
)
dirvec_print
(
struct
client
*
client
,
const
struct
dirvec
*
dv
)
{
{
size_t
i
;
size_t
i
;
...
@@ -30,15 +30,11 @@ dirvec_print(struct client *client, const struct dirvec *dv)
...
@@ -30,15 +30,11 @@ dirvec_print(struct client *client, const struct dirvec *dv)
for
(
i
=
0
;
i
<
dv
->
nr
;
++
i
)
for
(
i
=
0
;
i
<
dv
->
nr
;
++
i
)
client_printf
(
client
,
DIRECTORY_DIR
"%s
\n
"
,
client_printf
(
client
,
DIRECTORY_DIR
"%s
\n
"
,
directory_get_path
(
dv
->
base
[
i
]));
directory_get_path
(
dv
->
base
[
i
]));
return
0
;
}
}
int
void
directory_print
(
struct
client
*
client
,
const
struct
directory
*
directory
)
directory_print
(
struct
client
*
client
,
const
struct
directory
*
directory
)
{
{
dirvec_print
(
client
,
&
directory
->
children
);
dirvec_print
(
client
,
&
directory
->
children
);
songvec_print
(
client
,
&
directory
->
songs
);
songvec_print
(
client
,
&
directory
->
songs
);
return
0
;
}
}
src/directory_print.h
View file @
8c743fd3
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
struct
client
;
struct
client
;
struct
directory
;
struct
directory
;
int
void
directory_print
(
struct
client
*
client
,
const
struct
directory
*
directory
);
directory_print
(
struct
client
*
client
,
const
struct
directory
*
directory
);
#endif
#endif
src/icy_server.c
View file @
8c743fd3
...
@@ -95,6 +95,7 @@ icy_server_metadata_page(const struct tag *tag, ...)
...
@@ -95,6 +95,7 @@ icy_server_metadata_page(const struct tag *tag, ...)
gchar
stream_title
[(
1
+
255
-
28
)
*
16
];
// Length + Metadata -
gchar
stream_title
[(
1
+
255
-
28
)
*
16
];
// Length + Metadata -
// "StreamTitle='';StreamUrl='';"
// "StreamTitle='';StreamUrl='';"
// = 4081 - 28
// = 4081 - 28
stream_title
[
0
]
=
'\0'
;
last_item
=
-
1
;
last_item
=
-
1
;
...
...
src/input/curl_input_plugin.c
View file @
8c743fd3
...
@@ -241,7 +241,6 @@ input_curl_select(struct input_curl *c)
...
@@ -241,7 +241,6 @@ input_curl_select(struct input_curl *c)
fd_set
rfds
,
wfds
,
efds
;
fd_set
rfds
,
wfds
,
efds
;
int
max_fd
,
ret
;
int
max_fd
,
ret
;
CURLMcode
mcode
;
CURLMcode
mcode
;
/* XXX hard coded timeout value.. */
struct
timeval
timeout
=
{
struct
timeval
timeout
=
{
.
tv_sec
=
1
,
.
tv_sec
=
1
,
.
tv_usec
=
0
,
.
tv_usec
=
0
,
...
@@ -260,7 +259,23 @@ input_curl_select(struct input_curl *c)
...
@@ -260,7 +259,23 @@ input_curl_select(struct input_curl *c)
return
-
1
;
return
-
1
;
}
}
assert
(
max_fd
>=
0
);
#if LIBCURL_VERSION_NUM >= 0x070f04
long
timeout2
;
mcode
=
curl_multi_timeout
(
c
->
multi
,
&
timeout2
);
if
(
mcode
!=
CURLM_OK
)
{
g_warning
(
"curl_multi_timeout() failed: %s
\n
"
,
curl_multi_strerror
(
mcode
));
return
-
1
;
}
if
(
timeout2
>=
0
)
{
if
(
timeout2
>
10000
)
timeout2
=
10000
;
timeout
.
tv_sec
=
timeout2
/
1000
;
timeout
.
tv_usec
=
(
timeout2
%
1000
)
*
1000
;
}
#endif
ret
=
select
(
max_fd
+
1
,
&
rfds
,
&
wfds
,
&
efds
,
&
timeout
);
ret
=
select
(
max_fd
+
1
,
&
rfds
,
&
wfds
,
&
efds
,
&
timeout
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
...
src/input/mms_input_plugin.c
View file @
8c743fd3
...
@@ -49,10 +49,13 @@ input_mms_open(struct input_stream *is, const char *url)
...
@@ -49,10 +49,13 @@ input_mms_open(struct input_stream *is, const char *url)
m
=
g_new
(
struct
input_mms
,
1
);
m
=
g_new
(
struct
input_mms
,
1
);
m
->
mms
=
mmsx_connect
(
NULL
,
NULL
,
url
,
128
*
1024
);
m
->
mms
=
mmsx_connect
(
NULL
,
NULL
,
url
,
128
*
1024
);
if
(
m
->
mms
==
NULL
)
{
if
(
m
->
mms
==
NULL
)
{
g_free
(
m
);
g_warning
(
"mmsx_connect() failed"
);
g_warning
(
"mmsx_connect() failed"
);
return
false
;
return
false
;
}
}
m
->
eof
=
false
;
/* XX is this correct? at least this selects the ffmpeg
/* XX is this correct? at least this selects the ffmpeg
decoder, which seems to work fine*/
decoder, which seems to work fine*/
is
->
mime
=
g_strdup
(
"audio/x-ms-wma"
);
is
->
mime
=
g_strdup
(
"audio/x-ms-wma"
);
...
...
src/input/rewind_input_plugin.c
View file @
8c743fd3
...
@@ -20,6 +20,9 @@
...
@@ -20,6 +20,9 @@
#include "config.h"
#include "config.h"
#include "input/rewind_input_plugin.h"
#include "input/rewind_input_plugin.h"
#include "input/curl_input_plugin.h"
#include "input/curl_input_plugin.h"
#ifdef ENABLE_MMS
#include "input/mms_input_plugin.h"
#endif
#include "input_plugin.h"
#include "input_plugin.h"
#include "tag.h"
#include "tag.h"
...
@@ -86,10 +89,11 @@ copy_attributes(struct input_stream *dest)
...
@@ -86,10 +89,11 @@ copy_attributes(struct input_stream *dest)
dest
->
size
=
src
->
size
;
dest
->
size
=
src
->
size
;
dest
->
offset
=
src
->
offset
;
dest
->
offset
=
src
->
offset
;
if
(
dest
->
mime
==
NULL
&&
src
->
mime
!=
NULL
)
if
(
src
->
mime
!=
NULL
)
{
/* this is set only once, and the duplicated pointer
if
(
dest
->
mime
!=
NULL
)
is freed by input_stream_close() */
g_free
(
dest
->
mime
);
dest
->
mime
=
g_strdup
(
src
->
mime
);
dest
->
mime
=
g_strdup
(
src
->
mime
);
}
}
}
static
void
static
void
...
@@ -219,7 +223,11 @@ input_rewind_open(struct input_stream *is)
...
@@ -219,7 +223,11 @@ input_rewind_open(struct input_stream *is)
assert
(
is
!=
NULL
);
assert
(
is
!=
NULL
);
assert
(
is
->
offset
==
0
);
assert
(
is
->
offset
==
0
);
if
(
is
->
plugin
!=
&
input_plugin_curl
)
if
(
is
->
plugin
!=
&
input_plugin_curl
#ifdef ENABLE_MMS
&&
is
->
plugin
!=
&
input_plugin_mms
#endif
)
/* due to limitations in the input_plugin API, we only
/* due to limitations in the input_plugin API, we only
(explicitly) support the CURL input plugin */
(explicitly) support the CURL input plugin */
return
;
return
;
...
@@ -229,6 +237,7 @@ input_rewind_open(struct input_stream *is)
...
@@ -229,6 +237,7 @@ input_rewind_open(struct input_stream *is)
/* move the CURL input stream to c->input */
/* move the CURL input stream to c->input */
c
->
input
=
*
is
;
c
->
input
=
*
is
;
if
(
is
->
plugin
==
&
input_plugin_curl
)
input_curl_reinit
(
&
c
->
input
);
input_curl_reinit
(
&
c
->
input
);
/* convert the existing input_stream pointer to a "rewind"
/* convert the existing input_stream pointer to a "rewind"
...
...
src/listen.c
View file @
8c743fd3
...
@@ -407,7 +407,13 @@ static int get_remote_uid(int fd)
...
@@ -407,7 +407,13 @@ static int get_remote_uid(int fd)
return
cred
.
uid
;
return
cred
.
uid
;
#else
#else
(
void
)
fd
;
#ifdef HAVE_GETPEEREID
uid_t
euid
;
gid_t
egid
;
if
(
getpeereid
(
fd
,
&
euid
,
&
egid
)
==
0
)
return
euid
;
#endif
return
-
1
;
return
-
1
;
#endif
#endif
}
}
...
...
src/locate.c
View file @
8c743fd3
...
@@ -42,8 +42,8 @@ locate_parse_type(const char *str)
...
@@ -42,8 +42,8 @@ locate_parse_type(const char *str)
if
(
0
==
g_ascii_strcasecmp
(
str
,
LOCATE_TAG_ANY_KEY
))
if
(
0
==
g_ascii_strcasecmp
(
str
,
LOCATE_TAG_ANY_KEY
))
return
LOCATE_TAG_ANY_TYPE
;
return
LOCATE_TAG_ANY_TYPE
;
for
(
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
i
++
)
i
=
tag_name_parse_i
(
str
);
if
(
0
==
g_ascii_strcasecmp
(
str
,
tag_item_names
[
i
])
)
if
(
i
!=
TAG_NUM_OF_ITEM_TYPES
)
return
i
;
return
i
;
return
-
1
;
return
-
1
;
...
...
src/notify.c
View file @
8c743fd3
...
@@ -48,3 +48,10 @@ void notify_signal(struct notify *notify)
...
@@ -48,3 +48,10 @@ void notify_signal(struct notify *notify)
g_cond_signal
(
notify
->
cond
);
g_cond_signal
(
notify
->
cond
);
g_mutex_unlock
(
notify
->
mutex
);
g_mutex_unlock
(
notify
->
mutex
);
}
}
void
notify_clear
(
struct
notify
*
notify
)
{
g_mutex_lock
(
notify
->
mutex
);
notify
->
pending
=
false
;
g_mutex_unlock
(
notify
->
mutex
);
}
src/notify.h
View file @
8c743fd3
...
@@ -45,4 +45,9 @@ void notify_wait(struct notify *notify);
...
@@ -45,4 +45,9 @@ void notify_wait(struct notify *notify);
*/
*/
void
notify_signal
(
struct
notify
*
notify
);
void
notify_signal
(
struct
notify
*
notify
);
/**
* Clears a pending notification.
*/
void
notify_clear
(
struct
notify
*
notify
);
#endif
#endif
src/output/httpd_output_plugin.c
View file @
8c743fd3
...
@@ -70,7 +70,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
...
@@ -70,7 +70,7 @@ httpd_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
}
}
if
(
strcmp
(
encoder_name
,
"vorbis"
)
==
0
)
if
(
strcmp
(
encoder_name
,
"vorbis"
)
==
0
)
httpd
->
content_type
=
"a
pplication/x-
ogg"
;
httpd
->
content_type
=
"a
udio/
ogg"
;
else
if
(
strcmp
(
encoder_name
,
"lame"
)
==
0
)
else
if
(
strcmp
(
encoder_name
,
"lame"
)
==
0
)
httpd
->
content_type
=
"audio/mpeg"
;
httpd
->
content_type
=
"audio/mpeg"
;
else
else
...
...
src/output_thread.c
View file @
8c743fd3
...
@@ -268,6 +268,16 @@ static gpointer audio_output_task(gpointer arg)
...
@@ -268,6 +268,16 @@ static gpointer audio_output_task(gpointer arg)
ao
->
chunk
=
NULL
;
ao
->
chunk
=
NULL
;
if
(
ao
->
open
)
if
(
ao
->
open
)
ao_plugin_cancel
(
ao
->
plugin
,
ao
->
data
);
ao_plugin_cancel
(
ao
->
plugin
,
ao
->
data
);
/* we must clear the notification now, because
the notify_wait() call below must wait
until audio_output_all_cancel() has cleared
the pipe; if another notification happens
to be still pending, we get a race
condition with a crash or an assertion
failure */
notify_clear
(
&
ao
->
notify
);
ao_command_finished
(
ao
);
ao_command_finished
(
ao
);
/* the player thread will now clear our music
/* the player thread will now clear our music
...
...
src/pcm_buffer.h
View file @
8c743fd3
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
* would put too much stress on the allocator.
* would put too much stress on the allocator.
*/
*/
struct
pcm_buffer
{
struct
pcm_buffer
{
char
*
buffer
;
void
*
buffer
;
size_t
size
;
size_t
size
;
};
};
...
...
src/player_thread.c
View file @
8c743fd3
...
@@ -90,6 +90,13 @@ struct player {
...
@@ -90,6 +90,13 @@ struct player {
unsigned
cross_fade_chunks
;
unsigned
cross_fade_chunks
;
/**
/**
* The tag of the "next" song during cross-fade. It is
* postponed, and sent to the output thread when the new song
* really begins.
*/
struct
tag
*
cross_fade_tag
;
/**
* The current audio format for the audio outputs.
* The current audio format for the audio outputs.
*/
*/
struct
audio_format
play_audio_format
;
struct
audio_format
play_audio_format
;
...
@@ -518,6 +525,14 @@ play_next_chunk(struct player *player)
...
@@ -518,6 +525,14 @@ play_next_chunk(struct player *player)
chunk
=
music_pipe_shift
(
player
->
pipe
);
chunk
=
music_pipe_shift
(
player
->
pipe
);
assert
(
chunk
!=
NULL
);
assert
(
chunk
!=
NULL
);
/* don't send the tags of the new song (which
is being faded in) yet; postpone it until
the current song is faded out */
player
->
cross_fade_tag
=
tag_merge_replace
(
player
->
cross_fade_tag
,
other_chunk
->
tag
);
other_chunk
->
tag
=
NULL
;
cross_fade_apply
(
chunk
,
other_chunk
,
cross_fade_apply
(
chunk
,
other_chunk
,
&
dc
.
out_audio_format
,
&
dc
.
out_audio_format
,
cross_fade_position
,
cross_fade_position
,
...
@@ -544,6 +559,14 @@ play_next_chunk(struct player *player)
...
@@ -544,6 +559,14 @@ play_next_chunk(struct player *player)
assert
(
chunk
!=
NULL
);
assert
(
chunk
!=
NULL
);
/* insert the postponed tag if cross-fading is finished */
if
(
player
->
xfade
!=
XFADE_ENABLED
&&
player
->
cross_fade_tag
!=
NULL
)
{
chunk
->
tag
=
tag_merge_replace
(
chunk
->
tag
,
player
->
cross_fade_tag
);
player
->
cross_fade_tag
=
NULL
;
}
/* play the current chunk */
/* play the current chunk */
success
=
play_chunk
(
player
->
song
,
chunk
,
&
player
->
play_audio_format
,
success
=
play_chunk
(
player
->
song
,
chunk
,
&
player
->
play_audio_format
,
...
@@ -608,6 +631,7 @@ static void do_play(void)
...
@@ -608,6 +631,7 @@ static void do_play(void)
.
xfade
=
XFADE_UNKNOWN
,
.
xfade
=
XFADE_UNKNOWN
,
.
cross_fading
=
false
,
.
cross_fading
=
false
,
.
cross_fade_chunks
=
0
,
.
cross_fade_chunks
=
0
,
.
cross_fade_tag
=
NULL
,
.
size_to_time
=
0
.
0
,
.
size_to_time
=
0
.
0
,
};
};
...
@@ -754,6 +778,9 @@ static void do_play(void)
...
@@ -754,6 +778,9 @@ static void do_play(void)
music_pipe_clear
(
player
.
pipe
,
player_buffer
);
music_pipe_clear
(
player
.
pipe
,
player_buffer
);
music_pipe_free
(
player
.
pipe
);
music_pipe_free
(
player
.
pipe
);
if
(
player
.
cross_fade_tag
!=
NULL
)
tag_free
(
player
.
cross_fade_tag
);
pc
.
state
=
PLAYER_STATE_STOP
;
pc
.
state
=
PLAYER_STATE_STOP
;
event_pipe_emit
(
PIPE_EVENT_PLAYLIST
);
event_pipe_emit
(
PIPE_EVENT_PLAYLIST
);
}
}
...
...
src/playlist.c
View file @
8c743fd3
...
@@ -140,7 +140,8 @@ playlist_update_queued_song(struct playlist *playlist, const struct song *prev)
...
@@ -140,7 +140,8 @@ playlist_update_queued_song(struct playlist *playlist, const struct song *prev)
?
queue_next_order
(
&
playlist
->
queue
,
playlist
->
current
)
?
queue_next_order
(
&
playlist
->
queue
,
playlist
->
current
)
:
0
;
:
0
;
if
(
next_order
==
0
&&
playlist
->
queue
.
random
)
{
if
(
next_order
==
0
&&
playlist
->
queue
.
random
&&
!
playlist
->
queue
.
single
)
{
/* shuffle the song order again, so we get a different
/* shuffle the song order again, so we get a different
order each time the playlist is played
order each time the playlist is played
completely */
completely */
...
...
src/playlist_control.c
View file @
8c743fd3
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include "playlist_internal.h"
#include "playlist_internal.h"
#include "player_control.h"
#include "player_control.h"
#include "idle.h"
#include <glib.h>
#include <glib.h>
...
@@ -156,6 +157,8 @@ nextSongInPlaylist(struct playlist *playlist)
...
@@ -156,6 +157,8 @@ nextSongInPlaylist(struct playlist *playlist)
if
(
next_order
<
0
)
{
if
(
next_order
<
0
)
{
/* cancel single */
/* cancel single */
playlist
->
queue
.
single
=
false
;
playlist
->
queue
.
single
=
false
;
idle_add
(
IDLE_OPTIONS
);
/* no song after this one: stop playback */
/* no song after this one: stop playback */
stopPlaylist
(
playlist
);
stopPlaylist
(
playlist
);
...
...
src/tag.c
View file @
8c743fd3
...
@@ -64,6 +64,36 @@ const char *tag_item_names[TAG_NUM_OF_ITEM_TYPES] = {
...
@@ -64,6 +64,36 @@ const char *tag_item_names[TAG_NUM_OF_ITEM_TYPES] = {
bool
ignore_tag_items
[
TAG_NUM_OF_ITEM_TYPES
];
bool
ignore_tag_items
[
TAG_NUM_OF_ITEM_TYPES
];
enum
tag_type
tag_name_parse
(
const
char
*
name
)
{
assert
(
name
!=
NULL
);
for
(
unsigned
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
++
i
)
{
assert
(
tag_item_names
[
i
]
!=
NULL
);
if
(
strcmp
(
name
,
tag_item_names
[
i
])
==
0
)
return
(
enum
tag_type
)
i
;
}
return
TAG_NUM_OF_ITEM_TYPES
;
}
enum
tag_type
tag_name_parse_i
(
const
char
*
name
)
{
assert
(
name
!=
NULL
);
for
(
unsigned
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
++
i
)
{
assert
(
tag_item_names
[
i
]
!=
NULL
);
if
(
g_ascii_strcasecmp
(
name
,
tag_item_names
[
i
])
==
0
)
return
(
enum
tag_type
)
i
;
}
return
TAG_NUM_OF_ITEM_TYPES
;
}
static
size_t
items_size
(
const
struct
tag
*
tag
)
static
size_t
items_size
(
const
struct
tag
*
tag
)
{
{
return
tag
->
num_items
*
sizeof
(
struct
tag_item
*
);
return
tag
->
num_items
*
sizeof
(
struct
tag_item
*
);
...
@@ -76,7 +106,7 @@ void tag_lib_init(void)
...
@@ -76,7 +106,7 @@ void tag_lib_init(void)
char
*
temp
;
char
*
temp
;
char
*
s
;
char
*
s
;
char
*
c
;
char
*
c
;
int
i
;
enum
tag_type
type
;
/* parse the "metadata_to_use" config parameter below */
/* parse the "metadata_to_use" config parameter below */
...
@@ -98,16 +128,18 @@ void tag_lib_init(void)
...
@@ -98,16 +128,18 @@ void tag_lib_init(void)
if
(
*
s
==
'\0'
)
if
(
*
s
==
'\0'
)
quit
=
1
;
quit
=
1
;
*
s
=
'\0'
;
*
s
=
'\0'
;
for
(
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
i
++
)
{
if
(
g_ascii_strcasecmp
(
c
,
tag_item_names
[
i
])
==
0
)
{
c
=
g_strstrip
(
c
);
ignore_tag_items
[
i
]
=
false
;
if
(
*
c
==
0
)
break
;
continue
;
}
}
type
=
tag_name_parse_i
(
c
);
if
(
strlen
(
c
)
&&
i
==
TAG_NUM_OF_ITEM_TYPES
)
{
if
(
type
==
TAG_NUM_OF_ITEM_TYPES
)
g_error
(
"error parsing metadata item
\"
%s
\"
"
,
g_error
(
"error parsing metadata item
\"
%s
\"
"
,
c
);
c
);
}
ignore_tag_items
[
type
]
=
false
;
s
++
;
s
++
;
c
=
s
;
c
=
s
;
}
}
...
@@ -247,6 +279,22 @@ tag_merge(const struct tag *base, const struct tag *add)
...
@@ -247,6 +279,22 @@ tag_merge(const struct tag *base, const struct tag *add)
return
ret
;
return
ret
;
}
}
struct
tag
*
tag_merge_replace
(
struct
tag
*
base
,
struct
tag
*
add
)
{
if
(
add
==
NULL
)
return
base
;
if
(
base
==
NULL
)
return
add
;
struct
tag
*
tag
=
tag_merge
(
base
,
add
);
tag_free
(
base
);
tag_free
(
add
);
return
tag
;
}
const
char
*
const
char
*
tag_get_value
(
const
struct
tag
*
tag
,
enum
tag_type
type
)
tag_get_value
(
const
struct
tag
*
tag
,
enum
tag_type
type
)
{
{
...
...
src/tag.h
View file @
8c743fd3
...
@@ -94,6 +94,22 @@ struct tag {
...
@@ -94,6 +94,22 @@ struct tag {
};
};
/**
/**
* Parse the string, and convert it into a #tag_type. Returns
* #TAG_NUM_OF_ITEM_TYPES if the string could not be recognized.
*/
enum
tag_type
tag_name_parse
(
const
char
*
name
);
/**
* Parse the string, and convert it into a #tag_type. Returns
* #TAG_NUM_OF_ITEM_TYPES if the string could not be recognized.
*
* Case does not matter.
*/
enum
tag_type
tag_name_parse_i
(
const
char
*
name
);
/**
* Creates an empty #tag.
* Creates an empty #tag.
*/
*/
struct
tag
*
tag_new
(
void
);
struct
tag
*
tag_new
(
void
);
...
@@ -166,6 +182,15 @@ struct tag *
...
@@ -166,6 +182,15 @@ struct tag *
tag_merge
(
const
struct
tag
*
base
,
const
struct
tag
*
add
);
tag_merge
(
const
struct
tag
*
base
,
const
struct
tag
*
add
);
/**
/**
* Merges the data from two tags. Any of the two may be NULL. Both
* are freed by this function.
*
* @return a newly allocated tag, which must be freed with tag_free()
*/
struct
tag
*
tag_merge_replace
(
struct
tag
*
base
,
struct
tag
*
add
);
/**
* Returns true if the tag contains no items. This ignores the "time"
* Returns true if the tag contains no items. This ignores the "time"
* attribute.
* attribute.
*/
*/
...
...
src/tag_ape.c
View file @
8c743fd3
...
@@ -19,12 +19,47 @@
...
@@ -19,12 +19,47 @@
#include "tag_ape.h"
#include "tag_ape.h"
#include "tag.h"
#include "tag.h"
#include "tag_table.h"
#include <glib.h>
#include <glib.h>
#include <assert.h>
#include <assert.h>
#include <stdio.h>
#include <stdio.h>
static
const
char
*
const
ape_tag_names
[
TAG_NUM_OF_ITEM_TYPES
]
=
{
[
TAG_ITEM_ALBUM_ARTIST
]
=
"album artist"
,
[
TAG_ITEM_DATE
]
=
"year"
};
static
enum
tag_type
tag_ape_name_parse
(
const
char
*
name
)
{
enum
tag_type
type
=
tag_table_lookup
(
ape_tag_names
,
name
);
if
(
type
==
TAG_NUM_OF_ITEM_TYPES
)
type
=
tag_name_parse_i
(
name
);
return
type
;
}
static
struct
tag
*
tag_ape_import_item
(
struct
tag
*
tag
,
unsigned
long
flags
,
const
char
*
key
,
const
char
*
value
,
size_t
value_length
)
{
/* we only care about utf-8 text tags */
if
((
flags
&
(
0x3
<<
1
))
!=
0
)
return
tag
;
enum
tag_type
type
=
tag_ape_name_parse
(
key
);
if
(
type
==
TAG_NUM_OF_ITEM_TYPES
)
return
tag
;
if
(
tag
==
NULL
)
tag
=
tag_new
();
tag_add_item_n
(
tag
,
type
,
value
,
value_length
);
return
tag
;
}
struct
tag
*
struct
tag
*
tag_ape_load
(
const
char
*
file
)
tag_ape_load
(
const
char
*
file
)
{
{
...
@@ -36,7 +71,6 @@ tag_ape_load(const char *file)
...
@@ -36,7 +71,6 @@ tag_ape_load(const char *file)
size_t
tagLen
;
size_t
tagLen
;
size_t
size
;
size_t
size
;
unsigned
long
flags
;
unsigned
long
flags
;
int
i
;
char
*
key
;
char
*
key
;
struct
{
struct
{
...
@@ -48,26 +82,6 @@ tag_ape_load(const char *file)
...
@@ -48,26 +82,6 @@ tag_ape_load(const char *file)
unsigned
char
reserved
[
8
];
unsigned
char
reserved
[
8
];
}
footer
;
}
footer
;
const
char
*
apeItems
[
7
]
=
{
"title"
,
"artist"
,
"album"
,
"comment"
,
"genre"
,
"track"
,
"year"
};
int
tagItems
[
7
]
=
{
TAG_ITEM_TITLE
,
TAG_ITEM_ARTIST
,
TAG_ITEM_ALBUM
,
TAG_ITEM_COMMENT
,
TAG_ITEM_GENRE
,
TAG_ITEM_TRACK
,
TAG_ITEM_DATE
,
};
fp
=
fopen
(
file
,
"r"
);
fp
=
fopen
(
file
,
"r"
);
if
(
!
fp
)
if
(
!
fp
)
return
NULL
;
return
NULL
;
...
@@ -127,17 +141,8 @@ tag_ape_load(const char *file)
...
@@ -127,17 +141,8 @@ tag_ape_load(const char *file)
if
(
tagLen
<
size
)
if
(
tagLen
<
size
)
goto
fail
;
goto
fail
;
/* we only care about utf-8 text tags */
ret
=
tag_ape_import_item
(
ret
,
flags
,
key
,
p
,
size
);
if
(
!
(
flags
&
(
0x3
<<
1
)))
{
for
(
i
=
0
;
i
<
7
;
i
++
)
{
if
(
g_ascii_strcasecmp
(
key
,
apeItems
[
i
])
==
0
)
{
if
(
!
ret
)
ret
=
tag_new
();
tag_add_item_n
(
ret
,
tagItems
[
i
],
p
,
size
);
}
}
}
p
+=
size
;
p
+=
size
;
tagLen
-=
size
;
tagLen
-=
size
;
}
}
...
...
src/tag_table.h
0 → 100644
View file @
8c743fd3
/*
* Copyright (C) 2003-2010 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_TAG_TABLE_H
#define MPD_TAG_TABLE_H
#include "tag.h"
#include <glib.h>
/**
* Looks up a string in a tag translation table (case insensitive).
* Returns TAG_NUM_OF_ITEM_TYPES if the specified name was not found
* in the table.
*/
static
inline
enum
tag_type
tag_table_lookup
(
const
char
*
const
*
table
,
const
char
*
name
)
{
for
(
unsigned
i
=
0
;
i
<
TAG_NUM_OF_ITEM_TYPES
;
i
++
)
if
(
table
[
i
]
!=
NULL
&&
g_ascii_strcasecmp
(
name
,
table
[
i
])
==
0
)
return
(
enum
tag_type
)
i
;
return
TAG_NUM_OF_ITEM_TYPES
;
}
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment