~q3cpma/mus

ref: cf29c2237d0c99e5240a55895c07564ef4635392 mus/mus_player/decoder.c -rw-r--r-- 3.2 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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

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

#ifdef USE_FLAC
#include "flac.h"
#endif

#ifdef USE_OGG_VORBIS
#include "vorbis.h"
#endif

#ifdef USE_OGG_OPUS
#include "opus.h"
#endif


#if !defined (USE_FLAC) || !defined (USE_OGG_VORBIS) || !defined (USE_OGG_OPUS)
static void * unsupported(int fd, Decoder *dec)
{
	(void)fd;
	log_append(LOG_ERR, "%s: %s support isn't enabled",
		dec->tinfo->path, audio_format_str[dec->tinfo->aufmt]);
	return NULL;
}
#endif

static void *(*decoder_init_func[NUM_AUDIO_FORMAT])(int, Decoder *) =
{
#ifdef USE_FLAC
	flac_init,
	flac_init, /* USE_FLAC contains both FLAC and Ogg FLAC support */
#else
	unsupported,
	unsupported,
#endif

#ifdef USE_OGG_VORBIS
	vorbis_init,
#else
	unsupported,
#endif

#ifdef USE_OGG_OPUS
	opus_init,
#else
	unsupported,
#endif
};

static void (*decoder_free_func[NUM_AUDIO_FORMAT])(void *) =
{
#ifdef USE_FLAC
	flac_free,
	flac_free,
#else
	NULL,
	NULL,
#endif

#ifdef USE_OGG_VORBIS
	vorbis_free,
#else
	NULL,
#endif

#ifdef USE_OGG_OPUS
	opus_free,
#else
	NULL,
#endif
};

static void *(*decoder_routine_func[NUM_AUDIO_FORMAT])(void *) =
{
#ifdef USE_FLAC
	flac_routine,
	flac_routine,
#else
	NULL,
	NULL,
#endif

#ifdef USE_OGG_VORBIS
	vorbis_routine,
#else
	NULL,
#endif

#ifdef USE_OGG_OPUS
	opus_routine,
#else
	NULL,
#endif
};


/* wrapper around open -> fadvise */
static int open_fadv(const char *path)
{
	int fd = open(path, O_RDONLY | O_CLOEXEC);
	if (fd == -1)
	{
		log_append(LOG_ERR, "%s: %s", path, strerror(errno));
		return -1;
	}
	int err = posix_fadvise(fd, 0, 0,
		POSIX_FADV_SEQUENTIAL | POSIX_FADV_WILLNEED);
	if (err != 0)
		log_append(LOG_ERR, "%s: %s", path, strerror(err));
	return fd;
}

bool decoder_init(Decoder *dec, int pipefd_wr, Track_info *tinfo,
	ReplayGain_type rgtype, const char *next)
{
	if (access(tinfo->path, R_OK))
	{
		log_append(LOG_ERR, "%s: file not found or not readable", tinfo->path);
		return false;
	}
	if (dec->next_fd != -1)
		dec->cur_fd = dec->next_fd;
	else
	{
		dec->cur_fd = open_fadv(tinfo->path);
		if (dec->cur_fd == -1)
			return false;
	}
	dec->next_fd = next ? open_fadv(next) : -1;

	dec->pipefd_wr = pipefd_wr;
	dec->tinfo = tinfo;
	dec->tinfo->aufmt = detect_audio_format(tinfo->path);
	dec->tinfo->duration = NULL;
	dec->tinfo->position = NULL;
	dec->rgtype = rgtype;
	dec->cancel_flag = false;
	tinfo->tags = tags_init();
	dec->ctx = decoder_init_func[dec->tinfo->aufmt](dec->cur_fd, dec);
	if (!dec->ctx)
	{
		decoder_clear(dec);
		return false;
	}

	dec->tinfo->gain = tag_compute_replay_gain(tinfo->tags, rgtype);
	return true;
}


void decoder_clear(const Decoder *dec)
{
	if (dec->ctx)
		decoder_free_func[dec->tinfo->aufmt](dec->ctx);
	tags_free(dec->tinfo->tags);
	duration_free(dec->tinfo->duration);
	duration_free(dec->tinfo->position);
}

void decoder_end(const Decoder *dec)
{
	xclose(dec->pipefd_wr);
}

bool decoder_spawn_thread(Decoder *dec)
{
	int err = pthread_create(&dec->tid, NULL,
		decoder_routine_func[dec->tinfo->aufmt], dec);
	if (err)
		log_append(LOG_ERR, "Decoding thread: %s", strerror(err));
	return !err;
}