diff --git a/CREDITS b/CREDITS index 2ef1bea3..d9cf7b17 100644 --- a/CREDITS +++ b/CREDITS @@ -1,4 +1,4 @@ -/* $Id$ */ +* $Id$ */ I've received lots of help from people on this project. @@ -110,6 +110,9 @@ Phil Packer Diego Penneno * Patches for multiple PID files to facilitate gentoo init scripts - +Patrick Kolla + * Popup "wizard" for smart playlists +slomo (from the forums) + * Musepack tag parsing support. diff --git a/admin-root/CREDITS b/admin-root/CREDITS index 381e99c8..d9cf7b17 100644 --- a/admin-root/CREDITS +++ b/admin-root/CREDITS @@ -112,3 +112,7 @@ Diego Penneno Patrick Kolla * Popup "wizard" for smart playlists + +slomo (from the forums) + * Musepack tag parsing support. + diff --git a/configure.in b/configure.in index af918a1c..53be74d2 100644 --- a/configure.in +++ b/configure.in @@ -68,10 +68,15 @@ AC_ARG_ENABLE(flac,[ --enable-flac Enable FLAC support], use_flac=true; CPPFLAGS="${CPPFLAGS} -DFLAC") +AC_ARG_ENABLE(musepack,[ --enable-musepack Enable Musepack support], + use_musepack=true; + CPPFLAGS="${CPPFLAGS} -DMUSEPACK") + AM_CONDITIONAL(COND_REND_HOWL, test x$rend_howl = xtrue) AM_CONDITIONAL(COND_REND_POSIX, test x$rend_posix = xtrue) AM_CONDITIONAL(COND_OGGVORBIS, test x$use_oggvorbis = xtrue) AM_CONDITIONAL(COND_FLAC, test x$use_flac = xtrue) +AM_CONDITIONAL(COND_MUSEPACK, test x$use_musepack = xtrue) AM_CONDITIONAL(COND_SQLITE,test x$db_sqlite = xtrue) AM_CONDITIONAL(COND_NEED_STRCASESTR,false) AM_CONDITIONAL(COND_NEED_STRSEP,false) @@ -209,6 +214,24 @@ if test x$use_flac = xtrue; then fi fi +if test x$use_musepack = xtrue; then + AC_PATH_PROG(TAGLIB_CONFIG, taglib-config, no) + AC_CHECK_HEADERS(taglib/tag_c.h,, [ + AC_MSG_ERROR([taglib/tag_c.h not found... TagLib must be installed for Musepack support])]) + if test "x$TAGLIB_CONFIG" = "xno" ; then + AC_MSG_ERROR(['TagLib must be installed for Musepack support']) + fi +dnl if test ! -e "`taglib-config --prefix`/lib/libtag_c.so.0"; then +dnl AC_MSG_ERROR(['Taglib C bindings are not installed']) +dnl fi + + if test x"$STATIC_LIBS" != x"no"; then + LDFLAGS="${LDFLAGS} ${STATIC_LIBS}/libtag_c.a" + else + LDFLAGS="${LDFLAGS} -ltag_c" + fi +fi + AC_REPLACE_FUNCS(strcasestr) AC_REPLACE_FUNCS(strsep) AC_CHECK_FUNCS(atoll) diff --git a/src/Makefile.am b/src/Makefile.am index fbfa07c1..bc8c906a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,6 +25,10 @@ if COND_FLAC FLACSRC=scan-flac.c endif +if COND_MUSEPACK +MUSEPACKSRC=scan-mpc.c +endif + if COND_SQLITE SQLITEDB=dbs-sqlite.c dbs-sqlite.h endif @@ -40,9 +44,9 @@ mt_daapd_SOURCES = main.c daapd.h rend.h uici.c uici.h webserver.c \ scan-xml.c scan-wma.c scan-aac.c scan-aac.h scan-wav.c scan-url.c \ smart-parser.c smart-parser.h \ $(PRENDSRC) $(ORENDSRC) $(HRENDSRC) $(OGGVORBISSRC) $(FLACSRC) \ - $(SQLITEDB) + $(MUSEPACKSRC) $(SQLITEDB) EXTRA_DIST = mDNS.c mDNSClientAPI.h mDNSDebug.h mDNSPosix.c \ mDNSUNP.c mDNSPlatformFunctions.h mDNSPosix.h mDNSUNP.h \ - rend-howl.c rend-posix.c rend-osx.c \ + rend-howl.c rend-posix.c rend-osx.c scan-mpc.c \ strcasestr.h scan-ogg.c scan-flac.c dbs-sqlite.c dbs-sqlite.h diff --git a/src/configfile.c b/src/configfile.c index b391bfbd..ed3451fe 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -1392,6 +1392,10 @@ void config_emit_flags(WS_CONNINFO *pwsc, void *value, char *arg) { ws_writefd(pwsc,"%s ","--enable-flac"); #endif +#ifdef MUSEPACK + ws_writefd(pwsc,"%s ","--enable-musepack"); +#endif + #ifdef WITH_GDBM ws_writefd(pwsc,"%s ","--with-gdbm"); #endif diff --git a/src/dbs-sqlite.c b/src/dbs-sqlite.c index d10945cc..b563c203 100644 --- a/src/dbs-sqlite.c +++ b/src/dbs-sqlite.c @@ -1721,16 +1721,20 @@ char *db_sqlite_upgrade_scripts[] = { "update songs set type=lower(type);\n" "update songs set type='m4a' where type='aac' or type='mp4';\n" "update songs set type='flac' where type='fla';\n" + "update songs set type='mpc' where type='mpp';\n" + "update songs set type='mpc' where type='mp+';\n" "update songs set description='AAC audio file' where type='m4a';\n" "update songs set description='MPEG audio file' where type='mp3';\n" "update songs set description='WAV audio file' where type='wav';\n" "update songs set description='Playlist URL' where type='pls';\n" "update songs set description='Ogg Vorbis audio file' where type='ogg';\n" "update songs set description='FLAC audio file' where type='flac';\n" + "update songs set description='Musepack audio file' where type='mpc';\n" "update songs set codectype='mp4a' where type='m4a' or type='m4p';\n" "update songs set codectype='mpeg' where type='mp3';\n" "update songs set codectype='ogg' where type='ogg';\n" "update songs set codectype='flac' where type='flac';\n" + "update songs set codectype='mpc' where type='mpc';\n" "update songs set force_update=1 where type='m4a';\n" /* look for alac */ "create index idx_path on songs(path);\n" "drop table tempsongs;\n" diff --git a/src/mp3-scanner.c b/src/mp3-scanner.c index 71a204d0..c4dd4f0b 100644 --- a/src/mp3-scanner.c +++ b/src/mp3-scanner.c @@ -90,6 +90,10 @@ extern int scan_get_ogginfo(char *filename, MP3FILE *pmp3); extern int scan_get_flacinfo(char *filename, MP3FILE *pmp3); #endif +#ifdef MUSEPACK +extern int scan_get_mpcinfo(char *filename, MP3FILE *pmp3); +#endif + extern int scan_get_wmainfo(char *filename, MP3FILE *pmp3); extern int scan_get_aacinfo(char *filename, MP3FILE *pmp3); extern int scan_get_wavinfo(char *filename, MP3FILE *pmp3); @@ -137,6 +141,11 @@ static TAGHANDLER taghandlers[] = { #ifdef FLAC { "flac", scan_get_flacinfo, "flac","flac", "FLAC audio file" }, { "fla", scan_get_flacinfo, "flac","flac", "FLAC audio file" }, +#endif +#ifdef MUSEPACK + { "mpc", scan_get_mpcinfo, "mpc", "mpc", "Musepack audio file" }, + { "mpp", scan_get_mpcinfo, "mpc", "mpc", "Musepack audio file" }, + { "mp+", scan_get_mpcinfo, "mpc", "mpc", "Musepack audio file" }, #endif { NULL, NULL, NULL, NULL, NULL } }; diff --git a/src/scan-mpc.c b/src/scan-mpc.c new file mode 100644 index 00000000..b49486d3 --- /dev/null +++ b/src/scan-mpc.c @@ -0,0 +1,124 @@ +/* + * $Id$ + * Musepack tag parsing routines. + * + * Copyright (C) 2005 Sebastian Dröge + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "mp3-scanner.h" +#include "err.h" + +#include +#include +#include +#include + +/** + * scan a musepack file for metainfo. + * + * @param filename file to read metainfo for + * @param pmp3 MP3FILE structure to fill + * @returns TRUE if file should be added to DB, FALSE otherwise + */ +int scan_get_mpcinfo(char *filename, MP3FILE *pmp3) { + FILE *f; + TagLib_File *file; + TagLib_Tag *tag; + TagLib_AudioProperties *properties; + char *val; + int len; + unsigned int i; + + /* get file length */ + if (!(f = fopen(filename, "rb"))) { + DPRINTF(E_WARN,L_SCAN,"Could not open %s for reading\n", filename); + return FALSE; + } + fseek(f, 0, SEEK_END); + pmp3->file_size = ftell(f); + fseek(f, 0, SEEK_SET); + fclose(f); + + /* open file with taglib */ + if ((file = taglib_file_new_type(filename, TagLib_File_MPC)) == NULL) { + DPRINTF(E_WARN,L_SCAN,"Could not open %s with taglib\n", filename); + return FALSE; + } + + /* retrieve all tags */ + if ((tag = taglib_file_tag(file)) == NULL) { + DPRINTF(E_WARN,L_SCAN,"Could not retrieve tags of %s\n", filename); + taglib_file_free(file); + + return FALSE; + } + + /* fill the MP3FILE structure with the tags */ + if ((val = taglib_tag_title(tag)) != NULL) { + len = strlen(val); + if ((pmp3->title = calloc(len + 1, 1)) != NULL) + strncpy(pmp3->title, val, len); + taglib_tag_free_strings(val); + } + if ((val = taglib_tag_artist(tag)) != NULL) { + len = strlen(val); + if ((pmp3->artist = calloc(len + 1, 1)) != NULL) + strncpy(pmp3->artist, val, len); + taglib_tag_free_strings(val); + } + if ((val = taglib_tag_album(tag)) != NULL) { + len = strlen(val); + if ((pmp3->album = calloc(len + 1, 1)) != NULL) + strncpy(pmp3->album, val, len); + taglib_tag_free_strings(val); + } + if ((val = taglib_tag_comment(tag)) != NULL) { + len = strlen(val); + if ((pmp3->comment = calloc(len + 1, 1)) != NULL) + strncpy(pmp3->comment, val, len); + taglib_tag_free_strings(val); + } + if ((val = taglib_tag_genre(tag)) != NULL) { + len = strlen(val); + if ((pmp3->genre = calloc(len + 1, 1)) != NULL) + strncpy(pmp3->genre, val, len); + taglib_tag_free_strings(val); + } + + if ((i = taglib_tag_year(tag)) != 0) + pmp3->year = i; + if ((i = taglib_tag_track(tag)) != 0) + pmp3->track = i; + + /* load the properties (like bitrate) from the file */ + if ((properties = taglib_file_audioproperties(file)) == NULL) { + DPRINTF(E_WARN,L_SCAN,"Could not retrieve properties of %s\n", filename); + return FALSE; + } + + /* fill the properties in the MP3FILE structure */ + pmp3->song_length = taglib_audioproperties_length(properties) * 1000; + pmp3->bitrate = taglib_audioproperties_bitrate(properties); + pmp3->samplerate = taglib_audioproperties_samplerate(properties); + + taglib_file_free(file); + + return TRUE; +} diff --git a/src/scanner-driver.c b/src/scanner-driver.c index 6530c68c..e2ca511d 100644 --- a/src/scanner-driver.c +++ b/src/scanner-driver.c @@ -39,6 +39,7 @@ extern int scan_get_wmainfo(char *filename, MP3FILE *pmp3); extern int scan_get_ogginfo(char *filename, MP3FILE *pmp3); extern int scan_get_flacinfo(char *filename, MP3FILE *pmp3); +extern int scan_get_mpcinfo(char *filename, MP3FILE *pmp3); extern int scan_get_wavinfo(char *filename, MP3FILE *pmp3); extern int scan_get_aacinfo(char *filename, MP3FILE *pmp3); extern int scan_get_mp3info(char *filename, MP3FILE *pmp3); @@ -59,6 +60,9 @@ SCANNERLIST scanner_list[] = { { "wma",scan_get_wmainfo }, { "flac",scan_get_flacinfo }, { "fla",scan_get_flacinfo }, + { "mpc",scan_get_mpcinfo }, + { "mpp",scan_get_mpcinfo }, + { "mp+",scan_get_mpcinfo }, { "ogg",scan_get_ogginfo }, { "m4a",scan_get_aacinfo }, { "m4p",scan_get_aacinfo }, diff --git a/src/scanner.mk b/src/scanner.mk index cba1c95a..a5a172a6 100644 --- a/src/scanner.mk +++ b/src/scanner.mk @@ -1,8 +1,8 @@ CC=gcc CFLAGS := $(CFLAGS) -g -I/sw/include -DHAVE_CONFIG_H -I. -I.. -LDFLAGS := $(LDFLAGS) -L/sw/lib -lid3tag -logg -lvorbisfile -lFLAC -lvorbis -bind_at_load +LDFLAGS := $(LDFLAGS) -L/sw/lib -lid3tag -logg -lvorbisfile -lFLAC -lvorbis -ltag_c TARGET = scanner -OBJECTS=scanner-driver.o restart.o err.o scan-wma.o scan-aac.o scan-wav.o scan-flac.o scan-ogg.o scan-mp3.o scan-url.o +OBJECTS=scanner-driver.o restart.o err.o scan-wma.o scan-aac.o scan-wav.o scan-flac.o scan-ogg.o scan-mp3.o scan-url.o scan-mpc.o $(TARGET): $(OBJECTS) $(CC) -o $(TARGET) $(LDFLAGS) $(OBJECTS)