Subversion Repositories mdb

Rev

Rev 33 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
32 andreas 1
/*
2
 * Copyright (C) 2015 by Andreas Theofilu <andreas@theosys.at>
3
 *
4
 * All rights reserved. No warranty, explicit or implicit, provided.
5
 *
6
 * NOTICE:  All information contained herein is, and remains
7
 * the property of Andreas Theofilu and his suppliers, if any.
8
 * The intellectual and technical concepts contained
9
 * herein are proprietary to Andreas Theofilu and its suppliers and
10
 * may be covered by European and Foreign Patents, patents in process,
11
 * and are protected by trade secret or copyright law.
12
 * Dissemination of this information or reproduction of this material
13
 * is strictly forbidden unless prior written permission is obtained
14
 * from Andreas Theofilu.
15
 */
16
#include <stdio.h>
17
#include <string.h>
18
#include <strings.h>
19
#include <unistd.h>
20
#include <stdlib.h>
21
#include <syslog.h>
22
#include <ao/ao.h>
23
#include <FLAC/stream_decoder.h>
24
 
25
#include "config.h"
26
#include "helplib.h"
27
#include "play.h"
28
#include "user.h"
29
 
30
static FLAC__StreamDecoderWriteStatus sdWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
31
static void sdMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
32
static void sdErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void * client_data);
33
 
34
FLAC__StreamDecoder *fsd;
35
static FLAC__uint64 total_samples = 0;
36
static unsigned sample_rate = 0;
37
static unsigned channels = 0;
38
static unsigned bps = 0;
39
ao_device *dev;
40
 
41
struct st_params
42
{
43
	int s1;
44
	int driver;
45
};
46
 
47
extern char aoOutPlayers[15][16];
48
 
49
void playFlac(int s1, char *file)
50
{
51
FLAC__StreamDecoderInitStatus initStatus;
52
int i, flag;
53
int driver;
54
struct st_params params;
55
 
56
	/* Check if we've a valid sound driver defined */
57
	flag = FALSE;
58
	i = 0;
59
 
60
	while (aoOutPlayers[i][0])
61
	{
62
		if (!strcasecmp(aoOutPlayers[i], configs.player))
63
		{
64
			flag = TRUE;
65
			break;
66
		}
67
 
68
		i++;
69
	}
70
 
71
	/* initializations */
72
	ao_initialize();
73
 
74
	if (flag)
75
	{
76
		if ((driver = ao_driver_id(configs.player)) == -1)
77
		{
78
			syslog(LOG_DAEMON, "Error finding the audio out driver %s!", configs.player);
79
			ao_shutdown();
80
			return;
81
		}
82
	}
83
	else if ((driver = ao_default_driver_id()) == -1)
84
	{
85
		syslog(LOG_DAEMON, "Error finding a default audio driver!");
86
		ao_shutdown();
87
		return;
88
	}
89
 
90
	if ((fsd = FLAC__stream_decoder_new()) == NULL)
91
	{
92
		syslog(LOG_DAEMON, "Error allocating memory for a new instance of FLAC stream decoder!");
93
		ao_shutdown();
94
		return;
95
	}
96
 
97
	(void)FLAC__stream_decoder_set_md5_checking(fsd, true);
98
 
99
	params.s1 = s1;
100
	params.driver = driver;
101
 
102
	if ((initStatus = FLAC__stream_decoder_init_file(fsd, file, sdWriteCallback, sdMetadataCallback, sdErrorCallback, (void *)&params)) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
103
	{
104
		char *txt;
105
 
106
		switch (initStatus)
107
		{
108
			case FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER:	txt = "The library was not compiled with support for the given container format."; break;
109
			case FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS:		txt = "A required callback was not supplied."; break;
110
			case FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR:	txt = "An error occurred allocating memory."; break;
111
			case FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE:		txt = "fopen() failed in FLAC__stream_decoder_init_file() or FLAC__stream_decoder_init_ogg_file()."; break;
112
			case FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED:		txt = "FLAC__stream_decoder_init_*() was called when the decoder was already initialized, usually because FLAC__stream_decoder_finish() was not called."; break;
113
 
114
			default:
115
				txt = "Unknown error!";
116
		}
117
 
118
		syslog(LOG_DAEMON, "Error initializing a file: %s", txt);
119
		FLAC__stream_decoder_finish(fsd);
120
		FLAC__stream_decoder_delete(fsd);
121
		ao_shutdown();
122
		return;
123
	}
124
 
125
	if (!FLAC__stream_decoder_process_until_end_of_stream(fsd))
126
	{
127
		syslog(LOG_DAEMON, "Error processing stream: %s", FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(fsd)]);
128
		FLAC__stream_decoder_finish(fsd);
129
		FLAC__stream_decoder_delete(fsd);
130
		ao_shutdown();
131
		return;
132
	}
133
 
134
	FLAC__stream_decoder_finish(fsd);
135
	FLAC__stream_decoder_delete(fsd);
136
	ao_shutdown();
137
}
138
 
139
FLAC__StreamDecoderWriteStatus sdWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
140
{
141
struct st_params *params = (struct st_params *)client_data;
142
int driver = params->driver;
143
int s1 = params->s1;
144
const FLAC__uint32 total_size = (FLAC__uint32)(total_samples * channels * (bps / 8));
145
size_t i, j;
146
int todo;
147
FLAC__uint16 *buf;
148
 
149
	if (total_samples == 0) 
150
	{
151
		syslog(LOG_DAEMON, "ERROR: FLAC file have to have a total_samples count in STREAMINFO");
152
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
153
	}
154
 
155
	if (channels != 2 || bps != 16) 
156
	{
157
		syslog(LOG_DAEMON, "ERROR: Currently only 16bit stereo streams supported!");
158
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
159
	}
160
 
161
	if (frame->header.channels != 2)
162
	{
163
		syslog(LOG_DAEMON, "ERROR: This frame contains %d channels (should be 2)", frame->header.channels);
164
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
165
	}
166
 
167
	if (buffer [0] == NULL) 
168
	{
169
		syslog(LOG_DAEMON, "ERROR: buffer [0] is NULL\n");
170
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
171
	}
172
 
173
	if(buffer[1] == NULL) 
174
	{
175
		syslog(LOG_DAEMON, "ERROR: buffer [1] is NULL\n");
176
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
177
	}
178
 
179
	todo = check_command(s1);
180
 
181
	if (todo == PLAY_STATUS_STOP)
182
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
183
	else if (todo == PLAY_STATUS_FWD)
184
	{
185
		FLAC__uint64 fr;
186
 
187
		FLAC__stream_decoder_get_decode_position(decoder, &fr);
188
		fr += 100;
189
		playStatus = PLAY_STATUS_PLAY;
190
 
191
		if (!FLAC__stream_decoder_seek_absolute(fsd, fr))
192
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
193
 
194
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
195
	}
196
	else if (todo == PLAY_STATUS_REW)
197
	{
198
		FLAC__uint64 fr;
199
 
200
		FLAC__stream_decoder_get_decode_position(decoder, &fr);
201
 
202
		if (fr > 100)
203
			fr -= 100;
204
		else
205
			fr = 0;
206
 
207
		playStatus = PLAY_STATUS_PLAY;
208
 
209
		if (!FLAC__stream_decoder_seek_absolute(fsd, fr))
210
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
211
 
212
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
213
	}
214
 
215
	/* write WAVE header before we write the first frame */
216
	if (frame->header.number.sample_number == 0) 
217
	{
218
		ao_sample_format format;
219
		char hv0[256];
220
		/* set the output format and open the output device */
221
		format.bits = bps;
222
		format.rate = sample_rate;
223
		format.channels = channels;
224
		format.byte_format = AO_FMT_NATIVE;
225
		format.matrix = 0;
226
 
227
		if ((dev = ao_open_live(driver, &format, NULL)) == NULL)
228
		{
229
			syslog(LOG_DAEMON, "Error opening live playback device: %s", strerror(errno));
230
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
231
		}
232
 
233
		playStatus = PLAY_STATUS_PLAY;
234
		strcpy (hv0, "PLAYER:PLAY;");
235
		write(s1, hv0, strlen(hv0));
236
	}
237
 
238
	/* allocate memory for the buffer */
239
	if ((buf = (FLAC__uint16 *)calloc(frame->header.blocksize * 2, sizeof(FLAC__uint16))) == NULL)
240
	{
241
		syslog(LOG_DAEMON, "Error allocating memory for a buffer!");
242
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
243
	}
244
 
245
	j = 0;
246
 
247
	for (i = 0; i < frame->header.blocksize; i++)
248
	{
249
		buf[j] = (FLAC__uint16)buffer[0][i];
250
		buf[j+1] = (FLAC__uint16)buffer[1][i];
251
		j += 2;
252
	}
253
 
254
	ao_play(dev, (char *)buf, frame->header.blocksize);
255
	free (buf);
256
 
257
	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
258
}
259
 
260
static void sdMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
261
{
262
	if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) 
263
	{
264
		/* save for later */
265
		total_samples = metadata->data.stream_info.total_samples;
266
		sample_rate = metadata->data.stream_info.sample_rate;
267
		channels = metadata->data.stream_info.channels;
268
		bps = metadata->data.stream_info.bits_per_sample;
269
	}
270
}
271
 
272
static void sdErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void * client_data)
273
{
274
	syslog(LOG_DAEMON, "Got error callback: %s", FLAC__StreamDecoderErrorStatusString[status]);
275
}