$NetBSD: patch-af,v 1.11 2022/06/06 12:12:47 martin Exp $ --- mserv/mserv.c.orig 2003-08-03 16:57:20.000000000 +0200 +++ mserv/mserv.c 2012-02-07 10:39:02.000000000 +0100 @@ -62,12 +62,27 @@ met: #include #include +#ifdef PARSE_OGG_INFO +#include +#include +#endif + #include "mserv.h" + +#ifdef HAVE_INTTYPES_H +#include +#define TIME_T_PRI_CAST uint64_t +#define TIME_T_PRI PRIu64 +#else +#define TIME_T_PRI_CAST unsigned long +#define TIME_T_PRI "lu" +#endif + #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 +94,13 @@ met: # define MIN(X,Y) (((X) < (Y)) ? (X) : (Y)) #endif +#ifndef HAVE_STRLCPY +#define strlcpy strncpy +#endif +#ifndef HAVE_STRTOUMAX +#define strtoumax strtoul +#endif + extern char *optarg; extern int optind; /* extern int getopt(int, char *const *, const char *); */ /* sunos ;( */ @@ -131,7 +153,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); @@ -224,7 +247,7 @@ int main(int argc, char *argv[]) int i; struct protoent *protocol; struct sockaddr_in sin; - int so_int; + int so_int, proto; int flags; char *mserv_root = NULL; char *mserv_conf = NULL; @@ -292,7 +315,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 +328,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); } @@ -427,8 +450,13 @@ int main(int argc, char *argv[]) if (mserv_verbose && mserv_port) printf("Port set via command line options to %d\n", mserv_port); + protocol = getprotobyname("IP"); - mserv_socket = socket(AF_INET, SOCK_STREAM, protocol->p_proto); + if (protocol) + proto = protocol->p_proto; + else + proto = IPPROTO_IP; + mserv_socket = socket(AF_INET, SOCK_STREAM, proto); if (mserv_socket == -1) { mserv_log("Socket error '%s'", strerror(errno)); mserv_closedown(1); @@ -1624,6 +1652,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 +1715,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 +1854,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 +1938,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 +2063,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); @@ -2043,7 +2089,7 @@ static t_track *mserv_loadtrk(const char /* ignore old line */ modified = 1; } else if (!stricmp(token, "_lastplay")) { - lastplay = atol(value); + lastplay = (time_t)strtoumax(value, NULL, 10); } else if (!stricmp(token, "_duration")) { duration = atol(value); } else if (!stricmp(token, "_miscinfo")) { @@ -2059,6 +2105,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 +2129,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 +2148,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 +2778,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; } @@ -2762,7 +2821,7 @@ int mserv_savechanges(void) fprintf(fd, "_name=%s\n", track->name); fprintf(fd, "_year=%d\n", track->year); fprintf(fd, "_genres=%s\n", track->genres); - fprintf(fd, "_lastplay=%lu\n", (unsigned long int)track->lastplay); + fprintf(fd, "_lastplay=%" TIME_T_PRI "\n", (TIME_T_PRI_CAST)track->lastplay); fprintf(fd, "_duration=%lu\n", track->duration); fprintf(fd, "_miscinfo=%s\n", track->miscinfo); for (rate = track->ratings; rate; rate = rate->next) { @@ -3430,3 +3489,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