~q3cpma/mus

ref: cf29c2237d0c99e5240a55895c07564ef4635392 mus/mus_player/format_detect.c -rw-r--r-- 2.4 KiB
cf29c223q3cpma Add a #pragma once to the new xoshiro128plus.h header 1 year, 7 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "format_detect.h"
#include "log.h"
#include "misc.h"

#define OGG_PAGE_HEADER_SIZE 28           /* cf. rfc3533 */
#define OGG_MAGIC            "OggS"       /* cf. rfc3533 */
#define OGG_VORBIS_IDENT     "\x01vorbis" /* cf. rfc5334 */
#define OGG_OPUS_IDENT       "OpusHead"   /* cf. rfc7845 */
#define OGG_FLAC_IDENT       "\177FLAC"   /* cf. rfc5334 */
#define OGG_IDENT_MAX_SIZE   8
/*cf. https://xiph.org/flac/format.html */
#define FLAC_IDENT           "fLaC"


static inline int memcmp_str(const void *s1, const char *s2)
{
	return memcmp(s1, s2, strlen(s2));
}

Audio_format detect_audio_format(const char *path)
{
	int fd = xopen(path, O_RDONLY);
	static char buf[OGG_PAGE_HEADER_SIZE + OGG_IDENT_MAX_SIZE];
	const char *ext = strrchr(path, '.');

	if (!strcmp(ext, ".ogg"))
	{
		if (!read_full(fd, buf, OGG_PAGE_HEADER_SIZE + OGG_IDENT_MAX_SIZE))
			LOG_DIE("%s: %s", path, strerror(errno));
		if (!memcmp_str(buf, OGG_MAGIC)) /* Try vorbis, opus then flac */
		{
			if (!memcmp_str(buf + OGG_PAGE_HEADER_SIZE, OGG_VORBIS_IDENT))
				return AUDIO_FORMAT_OGG_VORBIS;
			if (!memcmp_str(buf + OGG_PAGE_HEADER_SIZE, OGG_OPUS_IDENT))
				return AUDIO_FORMAT_OGG_OPUS;
			if (!memcmp_str(buf + OGG_PAGE_HEADER_SIZE, OGG_FLAC_IDENT))
				return AUDIO_FORMAT_OGG_FLAC;
			log_append(LOG_ERR, "%s: ogg file with unknown codec", path);
			return AUDIO_FORMAT_UNKNOWN;
		}
		log_append(LOG_ERR, "%s: ogg extension but not an ogg file", path);
		return AUDIO_FORMAT_UNKNOWN;
	}
	if (!strcmp(ext, ".opus"))
	{
		if (!read_full(fd, buf, OGG_PAGE_HEADER_SIZE + OGG_IDENT_MAX_SIZE))
			LOG_DIE("%s: %s", path, strerror(errno));
		if (!memcmp_str(buf, OGG_MAGIC))
		{
			if (!memcmp_str(buf + OGG_PAGE_HEADER_SIZE, OGG_OPUS_IDENT))
				return AUDIO_FORMAT_OGG_OPUS;
			log_append(LOG_ERR, "%s: ogg file with unknown codec", path);
			return AUDIO_FORMAT_UNKNOWN;
		}
		log_append(LOG_ERR, "%s: opus extension but not an ogg file", path);
		return AUDIO_FORMAT_UNKNOWN;
	}
	if (!strcmp(ext, ".flac"))
	{
		if (!read_full(fd, buf, strlen(FLAC_IDENT)))
			LOG_DIE("%s: %s", path, strerror(errno));
		if (!memcmp_str(buf, FLAC_IDENT))
			return AUDIO_FORMAT_FLAC;
		log_append(LOG_ERR, "%s: flac extension but not a flac file", path);
		return AUDIO_FORMAT_UNKNOWN;
	}
	xclose(fd);
	return AUDIO_FORMAT_UNKNOWN;
}