$NetBSD: patch-af,v 1.9 2004/09/12 05:08:28 minskim Exp $ --- mserv/mserv.c.orig 2003-08-03 09:57:20.000000000 -0500 +++ mserv/mserv.c @@ -62,12 +62,17 @@ met: #include #include +#ifdef PARSE_OGG_INFO +#include +#include +#endif + #include "mserv.h" #include "misc.h" #include "cmd.h" #include "acl.h" #include "mp3info.h" -#include "soundcard.h" +#include "mservsoundcard.h" #include "defconf.h" #include "conf.h" #include "opt.h" @@ -79,6 +84,10 @@ met: # define MIN(X,Y) (((X) < (Y)) ? (X) : (Y)) #endif +#ifndef HAVE_STRLCPY +#define strlcpy strncpy +#endif + extern char *optarg; extern int optind; /* extern int getopt(int, char *const *, const char *); */ /* sunos ;( */ @@ -131,7 +140,8 @@ static void mserv_vresponse(t_client *cl static void mserv_scandir(void); static void mserv_scandir_recurse(const char *pathname); static t_track *mserv_loadtrk(const char *filename); -static t_album *mserv_loadalbum(const char *filename, int onlyifexists); +static t_album *mserv_loadalbum(const char *filename, int onlyifexists, + const char *default_author); static int album_insertsort(t_album *album); static t_author *mserv_authorlist(void); static int author_insertsort(t_author **list, t_author *author); @@ -292,7 +302,7 @@ int main(int argc, char *argv[]) ps->pw_dir[strlen(ps->pw_dir)-1] == '/' ? "" : "/"); } else { /* copy out of environment */ - if ((m = malloc(strlen(mserv_root))) == NULL) { + if ((m = malloc(strlen(mserv_root)+1)) == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } @@ -305,7 +315,7 @@ int main(int argc, char *argv[]) l--; mserv_root[l] = '\0'; if (!mserv_conf) { - if ((m = malloc(strlen(mserv_root)+sizeof("/config"))) == NULL) { + if ((m = malloc(strlen(mserv_root)+sizeof("/config")+1)) == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } @@ -1624,6 +1634,7 @@ static void mserv_scandir_recurse(const int i; t_album *album; int flag = 0; + const char *default_author = 0; /* pathname is "" or "directory/" or "directory/directory/..." */ @@ -1686,22 +1697,32 @@ static void mserv_scandir_recurse(const toomany = 1; break; } + if (mserv_verbose) mserv_log("Track file: %s", fullpath); if ((tracks[tnum] = mserv_loadtrk(filename)) == NULL) { mserv_log("Unable to add track '%s'", fullpath); } else { + + if (default_author == 0) + default_author = tracks[tnum]->author; + else if (default_author != (const char *)-1 && strcmp(default_author, + tracks[tnum]->author)) + default_author = (const char *)-1; + tracks[tnum]->id = mserv_nextid_track++; tracks[tnum]->n_album = mserv_nextid_album; tracks[tnum]->n_track = tnum+1; tracks[tnum]->next = mserv_tracks; mserv_tracks = tracks[tnum++]; } + flag = 1; /* there is at least one track in this directory */ } closedir(dir); /* load album, but only if there is an album file or flag is set */ - if ((album = mserv_loadalbum(pathname, flag ? 0 : 1)) == NULL) + if ((album = mserv_loadalbum(pathname, flag ? 0 : 1, + (default_author == (const char *)-1) ?0 :default_author)) == NULL) return; qsort(tracks, TRACKSPERALBUM, sizeof(t_track *), mserv_trackcompare_filename); @@ -1815,7 +1836,7 @@ static int mserv_trackcompare_rating(con } } -static t_album *mserv_loadalbum(const char *filename, int onlyifexists) +static t_album *mserv_loadalbum(const char *filename, int onlyifexists, const char *default_author) { FILE *fd; char fullpath[MAXFNAME]; @@ -1899,8 +1920,13 @@ static t_album *mserv_loadalbum(const ch return NULL; mtime = time(NULL); } - if (!*author) - strcpy(author, "!-Unindexed"); + if (!*author) { + if (default_author) + strcpy(author, default_author); + else + strcpy(author, "!-Unindexed"); + } + if (!*name) { if (!*filename || !*(filename+1)) { strcpy(name, "rootdir"); @@ -2019,11 +2045,13 @@ static t_track *mserv_loadtrk(const char alen = strlen(buffer); if (buffer[alen-1] != '\n') { mserv_log("Line %d too long in '%s'", line, fullpath_trk); + fclose(fd); return NULL; } buffer[--alen] = '\0'; if (!(l = strcspn(buffer, "=")) || l >= 64) { mserv_log("Invalid track line %d in '%s'", line, fullpath_trk); + fclose(fd); return NULL; } strncpy(token, buffer, l); @@ -2059,6 +2087,7 @@ static t_track *mserv_loadtrk(const char } if ((arate = malloc(sizeof(t_rating)+strlen(token)+1)) == NULL) { mserv_log("Out of memory creating ratings for '%s'", fullpath_trk); + fclose(fd); return NULL; } memset(arate, 0, sizeof(t_rating)); @@ -2082,15 +2111,18 @@ static t_track *mserv_loadtrk(const char } if (!*author) { mserv_log("No author specified in '%s'", fullpath_trk); + fclose(fd); return NULL; } if (!*name) { mserv_log("No name specified in '%s'", fullpath_trk); + fclose(fd); return NULL; } if (fstat(fileno(fd), &buf) == -1) { perror("fstat"); mserv_log("Unable to stat '%s': %s", filename, strerror(errno)); + fclose(fd); return NULL; } mtime = buf.st_mtime; @@ -2098,8 +2130,17 @@ static t_track *mserv_loadtrk(const char } if (duration == 0 && !*miscinfo) { len = strlen(fullpath_file); +#ifdef PARSE_OGG_INFO + if (len > 4 && !stricmp(".mp3", fullpath_file+len-4) || + !stricmp(".ogg", fullpath_file+len-4)) { + if (!stricmp(".mp3", fullpath_file+len-4)) + duration = mserv_mp3info_readlen(fullpath_file, &bitrate, &id3tag); + else + duration = mserv_ogginfo_readlen(fullpath_file, &bitrate, &id3tag); +#else if (len > 4 && !stricmp(".mp3", fullpath_file+len-4)) { duration = mserv_mp3info_readlen(fullpath_file, &bitrate, &id3tag); +#endif if (duration == -1) { mserv_log("Unable to determine details of mp3 '%s': %s", filename, strerror(errno)); @@ -2719,7 +2760,7 @@ t_album *mserv_checkdisk_album(t_album * } if (buf.st_mtime == album->mtime) return album; - if ((newalbum = mserv_loadalbum(album->filename, 1)) == NULL) { + if ((newalbum = mserv_loadalbum(album->filename, 1, 0)) == NULL) { mserv_log("Unable to re-load '%s'", album->filename); return album; } @@ -3430,3 +3471,59 @@ int mserv_setmixer(t_client *cl, int wha } #endif + +#ifdef PARSE_OGG_INFO +int mserv_ogginfo_readlen(const char *fname, int *bitrate_ret, + t_id3tag *id3tag) +{ + OggVorbis_File vf; + FILE *f; + ogg_sync_state sync; + vorbis_info *vi; + vorbis_comment *vc; + char **comment; + double duration; + + if (id3tag) + memset(id3tag, 0, sizeof(*id3tag)); + + if ((f = fopen(fname, "rb")) == NULL) + return -1; + + if (ov_open(f, &vf, NULL, 0) < 0) { + fclose(f); + return -1; + } + + if ( !(vi = ov_info(&vf, -1)) || !(vc = ov_comment(&vf, -1))) { + ov_clear(&vf); + fclose(f); + return -1; + } + + if (bitrate_ret) + *bitrate_ret = vi->bitrate_nominal/1024; + + for (comment = vc->user_comments ; *comment ; ++comment) { + if (strncasecmp(*comment, "title=", 6) == 0) { + strlcpy(id3tag->title, *comment + 6, MP3ID3_TITLELEN+1); + id3tag->present = 1; + } + else if (strncasecmp(*comment, "artist=", 7) == 0) + strlcpy(id3tag->artist, *comment + 7, MP3ID3_ARTISTLEN+1); + else if (strncasecmp(*comment, "album=", 6) == 0) + strlcpy(id3tag->album, *comment + 6, MP3ID3_ALBUMLEN+1); + else if (strncasecmp(*comment, "date=", 5) == 0) + strlcpy(id3tag->year, *comment + 5, MP3ID3_YEARLEN+1); + else if (strncasecmp(*comment, "genre=", 6) == 0) + strlcpy(id3tag->genre, *comment + 6, 31); + /* tracknumber ignored */ + } + + duration = ov_time_total(&vf, -1); + ov_clear(&vf); + fclose(f); + return (int)duration * 100; +} + +#endif