commit bf19b03e6400fa3a7573b0ba4fd057767f0adc22 from: Omar Polo date: Mon May 09 16:56:50 2022 UTC add a simple filetype detector instead of relying on file extension just a bit of "magic" :) Flac are easy, they always start with "fLaC". mp3 are weird because they either start with "ID3" (but this theoretically only ensures that's a tagged file, not an mp3) or 0xFF 0xFB. Ogg Opus should have a magic sequence "OpusHead" somewhere near the start of the file but also have the ogg' "OggS" magic bytes. I hope it's enough to distinguish between Ogg Opus and Vorbis. Another option would be to refactor play_oggvorbis/opus to not close the file on failure and try in cascade the play_* functions, but it's more complex and this solution seems to be enough. commit - 184600a89b139d44c106a366c351bee471185137 commit + bf19b03e6400fa3a7573b0ba4fd057767f0adc22 blob - 61834acffd9976fb86f0c0e41dd7624eaa494618 blob + 8a11967a55fb6e34c043591ae23d80109c613d8c --- player.c +++ player.c @@ -199,22 +199,38 @@ player_sendeof(void) int player_playnext(void) { + static char buf[512]; + ssize_t r; int fd = nextfd; assert(nextfd != -1); nextfd = -1; - /* XXX: use magic(5) for this, not file extensions */ - if (strstr(nextpath, ".ogg") != NULL) - return play_oggvorbis(fd); - else if (strstr(nextpath, ".mp3") != NULL) - return play_mp3(fd); - else if (strstr(nextpath, ".flac") != NULL) - return play_flac(fd); - else if (strstr(nextpath, ".opus") != NULL) + r = read(fd, buf, sizeof(buf)); + + /* 8 byte is the larger magic number */ + if (r < 8) { + log_warn("failed to read %s", nextpath); + goto err; + } + + if (lseek(fd, 0, SEEK_SET) == -1) { + log_warn("lseek failed"); + goto err; + } + + if (memcmp(buf, "fLaC", 4) == 0) + return play_flac(fd); + if (memcmp(buf, "ID3", 3) == 0 || + memcmp(buf, "\xFF\xFB", 2) == 0) + return play_mp3(fd); + if (memmem(buf, r, "OpusHead", 8) != NULL) return play_opus(fd); + if (memmem(buf, r, "OggS", 4) != NULL) + return play_oggvorbis(fd); log_warnx("unknown file type for %s", nextpath); +err: close(fd); return -1; }