Subversion Repositories mdb

Rev

Rev 32 | Rev 35 | Go to most recent revision | Details | Compare with Previous | 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;
33 andreas 39
static unsigned total_seconds;
32 andreas 40
ao_device *dev;
41
 
42
struct st_params
43
{
44
	int s1;
45
	int driver;
46
};
47
 
48
extern char aoOutPlayers[15][16];
49
 
50
void playFlac(int s1, char *file)
51
{
52
int i, flag;
53
int driver;
33 andreas 54
char hv0[64];
32 andreas 55
struct st_params params;
56
 
57
	/* Check if we've a valid sound driver defined */
58
	flag = FALSE;
59
	i = 0;
60
 
61
	while (aoOutPlayers[i][0])
62
	{
63
		if (!strcasecmp(aoOutPlayers[i], configs.player))
64
		{
65
			flag = TRUE;
66
			break;
67
		}
68
 
69
		i++;
70
	}
71
 
72
	/* initializations */
73
	ao_initialize();
74
 
75
	if (flag)
76
	{
77
		if ((driver = ao_driver_id(configs.player)) == -1)
78
		{
79
			syslog(LOG_DAEMON, "Error finding the audio out driver %s!", configs.player);
80
			ao_shutdown();
81
			return;
82
		}
83
	}
84
	else if ((driver = ao_default_driver_id()) == -1)
85
	{
86
		syslog(LOG_DAEMON, "Error finding a default audio driver!");
87
		ao_shutdown();
88
		return;
89
	}
90
 
91
	if ((fsd = FLAC__stream_decoder_new()) == NULL)
92
	{
93
		syslog(LOG_DAEMON, "Error allocating memory for a new instance of FLAC stream decoder!");
94
		ao_shutdown();
95
		return;
96
	}
97
 
98
	(void)FLAC__stream_decoder_set_md5_checking(fsd, true);
99
 
100
	params.s1 = s1;
101
	params.driver = driver;
102
 
33 andreas 103
	if (FLAC__stream_decoder_init_file(fsd, file, sdWriteCallback, sdMetadataCallback, sdErrorCallback, (void *)&params) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
32 andreas 104
	{
33 andreas 105
		syslog(LOG_DAEMON, "Error initializing file: %s [%s]", file, FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(fsd)]);
32 andreas 106
		FLAC__stream_decoder_finish(fsd);
107
		FLAC__stream_decoder_delete(fsd);
108
		ao_shutdown();
109
		return;
110
	}
111
 
112
	if (!FLAC__stream_decoder_process_until_end_of_stream(fsd))
113
	{
114
		syslog(LOG_DAEMON, "Error processing stream: %s", FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(fsd)]);
115
		FLAC__stream_decoder_finish(fsd);
116
		FLAC__stream_decoder_delete(fsd);
117
		ao_shutdown();
118
		return;
119
	}
120
 
33 andreas 121
	/* clean up */
122
	strcpy(hv0, "PLAYER:STOP;");
123
	write (s1, hv0, strlen(hv0));
124
 
125
	ao_close(dev);
32 andreas 126
	FLAC__stream_decoder_finish(fsd);
127
	FLAC__stream_decoder_delete(fsd);
128
	ao_shutdown();
129
}
130
 
131
FLAC__StreamDecoderWriteStatus sdWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
132
{
133
struct st_params *params = (struct st_params *)client_data;
134
int driver = params->driver;
135
int s1 = params->s1;
136
const FLAC__uint32 total_size = (FLAC__uint32)(total_samples * channels * (bps / 8));
137
size_t i, j;
138
int todo;
139
FLAC__uint16 *buf;
33 andreas 140
unsigned second;
32 andreas 141
 
142
	if (total_samples == 0) 
143
	{
144
		syslog(LOG_DAEMON, "ERROR: FLAC file have to have a total_samples count in STREAMINFO");
145
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
146
	}
147
 
148
	if (channels != 2 || bps != 16) 
149
	{
150
		syslog(LOG_DAEMON, "ERROR: Currently only 16bit stereo streams supported!");
151
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
152
	}
153
 
154
	if (frame->header.channels != 2)
155
	{
156
		syslog(LOG_DAEMON, "ERROR: This frame contains %d channels (should be 2)", frame->header.channels);
157
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
158
	}
159
 
160
	if (buffer [0] == NULL) 
161
	{
162
		syslog(LOG_DAEMON, "ERROR: buffer [0] is NULL\n");
163
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
164
	}
165
 
166
	if(buffer[1] == NULL) 
167
	{
168
		syslog(LOG_DAEMON, "ERROR: buffer [1] is NULL\n");
169
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
170
	}
171
 
172
	todo = check_command(s1);
173
 
174
	if (todo == PLAY_STATUS_STOP)
175
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
176
	else if (todo == PLAY_STATUS_FWD)
177
	{
178
		FLAC__uint64 fr;
179
 
180
		FLAC__stream_decoder_get_decode_position(decoder, &fr);
181
		fr += 100;
182
		playStatus = PLAY_STATUS_PLAY;
183
 
184
		if (!FLAC__stream_decoder_seek_absolute(fsd, fr))
185
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
186
 
187
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
188
	}
189
	else if (todo == PLAY_STATUS_REW)
190
	{
191
		FLAC__uint64 fr;
192
 
193
		FLAC__stream_decoder_get_decode_position(decoder, &fr);
194
 
195
		if (fr > 100)
196
			fr -= 100;
197
		else
198
			fr = 0;
199
 
200
		playStatus = PLAY_STATUS_PLAY;
201
 
202
		if (!FLAC__stream_decoder_seek_absolute(fsd, fr))
203
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
204
 
205
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
206
	}
207
 
33 andreas 208
	/* Initialize audio out device */
32 andreas 209
	if (frame->header.number.sample_number == 0) 
210
	{
211
		ao_sample_format format;
212
		char hv0[256];
213
		/* set the output format and open the output device */
214
		format.bits = bps;
215
		format.rate = sample_rate;
216
		format.channels = channels;
217
		format.byte_format = AO_FMT_NATIVE;
218
		format.matrix = 0;
33 andreas 219
 
32 andreas 220
		if ((dev = ao_open_live(driver, &format, NULL)) == NULL)
33 andreas 221
/*		{ */
32 andreas 222
			syslog(LOG_DAEMON, "Error opening live playback device: %s", strerror(errno));
33 andreas 223
/*			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
32 andreas 224
		}
33 andreas 225
*/
32 andreas 226
		playStatus = PLAY_STATUS_PLAY;
227
		strcpy (hv0, "PLAYER:PLAY;");
228
		write(s1, hv0, strlen(hv0));
229
	}
230
 
231
	/* allocate memory for the buffer */
232
	if ((buf = (FLAC__uint16 *)calloc(frame->header.blocksize * 2, sizeof(FLAC__uint16))) == NULL)
233
	{
234
		syslog(LOG_DAEMON, "Error allocating memory for a buffer!");
235
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
236
	}
237
 
238
	j = 0;
239
 
240
	for (i = 0; i < frame->header.blocksize; i++)
241
	{
242
		buf[j] = (FLAC__uint16)buffer[0][i];
243
		buf[j+1] = (FLAC__uint16)buffer[1][i];
244
		j += 2;
245
	}
246
 
33 andreas 247
	if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER)
248
	{
249
		char hv0[255], hv1[32], hv2[32], hv3[32];
250
 
251
		second = frame->header.number.sample_number / sample_rate;
252
		sprintf(hv0, "POSITION:%s:%s:%s;", secondsToString(second, &hv1[0]), secondsToString(total_seconds - second, &hv2[0]), secondsToString(total_seconds, &hv3[0]));
253
		write(s1, hv0, strlen(hv0));
254
	}
255
 
32 andreas 256
	ao_play(dev, (char *)buf, frame->header.blocksize);
257
	free (buf);
258
 
259
	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
260
}
261
 
262
static void sdMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
263
{
264
	if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) 
265
	{
266
		/* save for later */
267
		total_samples = metadata->data.stream_info.total_samples;
268
		sample_rate = metadata->data.stream_info.sample_rate;
269
		channels = metadata->data.stream_info.channels;
270
		bps = metadata->data.stream_info.bits_per_sample;
33 andreas 271
		total_seconds = (unsigned)total_samples / sample_rate;
32 andreas 272
	}
273
}
274
 
275
static void sdErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void * client_data)
276
{
277
	syslog(LOG_DAEMON, "Got error callback: %s", FLAC__StreamDecoderErrorStatusString[status]);
278
}