Subversion Repositories mdb

Rev

Rev 40 | 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>
35 andreas 23
#include <FLAC/all.h>
32 andreas 24
 
25
#include "config.h"
26
#include "helplib.h"
27
#include "play.h"
28
#include "user.h"
56 andreas 29
#include "mdb.h"
32 andreas 30
 
31
static FLAC__StreamDecoderWriteStatus sdWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
32
static void sdMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
33
static void sdErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void * client_data);
34
 
35
FLAC__StreamDecoder *fsd;
36
static FLAC__uint64 total_samples = 0;
35 andreas 37
static unsigned current_sample;
32 andreas 38
static unsigned sample_rate = 0;
39
static unsigned channels = 0;
40
static unsigned bps = 0;
35 andreas 41
static unsigned total_seconds, elapsed_seconds, old_second;
42
static double f_el_time;
32 andreas 43
ao_device *dev;
35 andreas 44
int last_todo;
32 andreas 45
 
46
struct st_params
47
{
48
	int s1;
49
	int driver;
50
};
51
 
52
extern char aoOutPlayers[15][16];
53
 
54
void playFlac(int s1, char *file)
55
{
56
int i, flag;
57
int driver;
56 andreas 58
/* char hv0[64]; */
32 andreas 59
struct st_params params;
60
 
61
	/* Check if we've a valid sound driver defined */
62
	flag = FALSE;
63
	i = 0;
64
 
65
	while (aoOutPlayers[i][0])
66
	{
67
		if (!strcasecmp(aoOutPlayers[i], configs.player))
68
		{
69
			flag = TRUE;
70
			break;
71
		}
72
 
73
		i++;
74
	}
75
 
76
	/* initializations */
77
	ao_initialize();
78
 
79
	if (flag)
80
	{
81
		if ((driver = ao_driver_id(configs.player)) == -1)
82
		{
83
			syslog(LOG_DAEMON, "Error finding the audio out driver %s!", configs.player);
84
			ao_shutdown();
85
			return;
86
		}
87
	}
88
	else if ((driver = ao_default_driver_id()) == -1)
89
	{
90
		syslog(LOG_DAEMON, "Error finding a default audio driver!");
91
		ao_shutdown();
92
		return;
93
	}
94
 
95
	if ((fsd = FLAC__stream_decoder_new()) == NULL)
96
	{
97
		syslog(LOG_DAEMON, "Error allocating memory for a new instance of FLAC stream decoder!");
98
		ao_shutdown();
99
		return;
100
	}
101
 
102
	(void)FLAC__stream_decoder_set_md5_checking(fsd, true);
103
 
104
	params.s1 = s1;
105
	params.driver = driver;
35 andreas 106
	current_sample = 0;
107
	old_second = 0;
108
	f_el_time = 0.0;
32 andreas 109
 
33 andreas 110
	if (FLAC__stream_decoder_init_file(fsd, file, sdWriteCallback, sdMetadataCallback, sdErrorCallback, (void *)&params) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
32 andreas 111
	{
33 andreas 112
		syslog(LOG_DAEMON, "Error initializing file: %s [%s]", file, FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(fsd)]);
32 andreas 113
		FLAC__stream_decoder_finish(fsd);
114
		FLAC__stream_decoder_delete(fsd);
115
		ao_shutdown();
116
		return;
117
	}
118
 
119
	if (!FLAC__stream_decoder_process_until_end_of_stream(fsd))
120
	{
35 andreas 121
		if (last_todo != PLAY_STATUS_STOP)
122
		{
40 andreas 123
			syslog(LOG_WARNING, "Error playing file %s", file);
124
			syslog(LOG_WARNING, "Error processing stream: %s", FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(fsd)]);
125
			ao_close(dev);
35 andreas 126
			FLAC__stream_decoder_finish(fsd);
127
			FLAC__stream_decoder_delete(fsd);
128
			ao_shutdown();
129
			last_todo = 0;
130
			return;
131
		}
32 andreas 132
	}
133
 
33 andreas 134
	/* clean up */
56 andreas 135
	handleWrite("PLAYER:STOP;");
136
/*	write (s1, hv0, strlen(hv0)); */
35 andreas 137
	last_todo = 0;
138
 
33 andreas 139
	ao_close(dev);
32 andreas 140
	FLAC__stream_decoder_finish(fsd);
141
	FLAC__stream_decoder_delete(fsd);
142
	ao_shutdown();
143
}
144
 
145
FLAC__StreamDecoderWriteStatus sdWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
146
{
147
struct st_params *params = (struct st_params *)client_data;
148
int driver = params->driver;
149
int s1 = params->s1;
35 andreas 150
uint_32 samples = frame->header.blocksize;
151
uint_32 decoded_size = frame->header.blocksize * frame->header.channels * (bps / 8);
152
static uint_8 aobuf[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(uint_32)]; /*oink!*/
40 andreas 153
uint_32 *u32aobuf = (uint_32 *) aobuf;
35 andreas 154
uint_16 *u16aobuf = (uint_16 *) aobuf;
155
uint_8   *u8aobuf = (uint_8  *) aobuf;
56 andreas 156
size_t i;
35 andreas 157
uint_32 sample, channel;
32 andreas 158
int todo;
159
 
160
	if (total_samples == 0) 
161
	{
162
		syslog(LOG_DAEMON, "ERROR: FLAC file have to have a total_samples count in STREAMINFO");
163
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
164
	}
165
 
40 andreas 166
	if (channels <= 0 || (bps != 32 && bps != 16 && bps != 8))
32 andreas 167
	{
40 andreas 168
		syslog(LOG_DAEMON, "ERROR: Currently only 8bit, 16bit or 32bit streams supported!");
32 andreas 169
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
170
	}
171
 
35 andreas 172
	if (buffer[0] == NULL) 
32 andreas 173
	{
174
		syslog(LOG_DAEMON, "ERROR: buffer [0] is NULL\n");
175
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
176
	}
177
 
35 andreas 178
	if (buffer[1] == NULL) 
32 andreas 179
	{
180
		syslog(LOG_DAEMON, "ERROR: buffer [1] is NULL\n");
181
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
182
	}
183
 
184
	todo = check_command(s1);
185
 
186
	if (todo == PLAY_STATUS_STOP)
35 andreas 187
	{
188
		last_todo = PLAY_STATUS_STOP;
32 andreas 189
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
35 andreas 190
	}
32 andreas 191
	else if (todo == PLAY_STATUS_FWD)
192
	{
193
		FLAC__uint64 fr;
194
 
195
		FLAC__stream_decoder_get_decode_position(decoder, &fr);
196
		fr += 100;
197
		playStatus = PLAY_STATUS_PLAY;
198
 
199
		if (!FLAC__stream_decoder_seek_absolute(fsd, fr))
200
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
201
 
202
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
203
	}
204
	else if (todo == PLAY_STATUS_REW)
205
	{
206
		FLAC__uint64 fr;
207
 
208
		FLAC__stream_decoder_get_decode_position(decoder, &fr);
209
 
210
		if (fr > 100)
211
			fr -= 100;
212
		else
213
			fr = 0;
214
 
215
		playStatus = PLAY_STATUS_PLAY;
216
 
217
		if (!FLAC__stream_decoder_seek_absolute(fsd, fr))
218
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
219
 
220
		return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
221
	}
222
 
33 andreas 223
	/* Initialize audio out device */
32 andreas 224
	if (frame->header.number.sample_number == 0) 
225
	{
226
		ao_sample_format format;
227
		char hv0[256];
228
		/* set the output format and open the output device */
229
		format.bits = bps;
230
		format.rate = sample_rate;
231
		format.channels = channels;
232
		format.byte_format = AO_FMT_NATIVE;
233
		format.matrix = 0;
33 andreas 234
 
32 andreas 235
		if ((dev = ao_open_live(driver, &format, NULL)) == NULL)
35 andreas 236
		{
237
			switch (errno)
238
			{
239
				case AO_ENODRIVER:	sprintf(hv0, "No driver corresponds to \"driver_id\"."); break;
240
				case AO_ENOTLIVE:	sprintf(hv0, "This driver (%s) is not a live output device.", configs.player); break;
241
				case AO_EBADOPTION:	sprintf(hv0, "A valid option key has an invalid value."); break;
242
				case AO_EOPENDEVICE:sprintf(hv0, "Cannot open the device."); break;
243
 
244
				default:
245
					sprintf(hv0, "%s", strerror(errno));
246
			}
247
 
248
			syslog(LOG_DAEMON, "Error opening live playback device: %s", hv0);
249
			return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
32 andreas 250
		}
35 andreas 251
 
32 andreas 252
		playStatus = PLAY_STATUS_PLAY;
56 andreas 253
		handleWrite("PLAYER:PLAY;");
254
/*		write(s1, hv0, strlen(hv0)); */
32 andreas 255
	}
256
 
35 andreas 257
	if (bps == 8)
32 andreas 258
	{
35 andreas 259
		for (sample = i = 0; sample < samples; sample++) 
260
		{
261
			for (channel = 0; channel < frame->header.channels; channel++,i++)
262
			{
263
				/* 8 bit wav data is unsigned */
264
				u8aobuf[i] = (uint_8)(buffer[channel][sample] + 0x80);
265
			}
266
		} 
32 andreas 267
	}
35 andreas 268
	else if (bps == 16)
32 andreas 269
	{
35 andreas 270
		for (sample = i = 0; sample < samples; sample++)
271
		{
272
			for(channel = 0; channel < frame->header.channels; channel++,i++)
273
				u16aobuf[i] = (uint_16)(buffer[channel][sample]);
274
		} 
32 andreas 275
	}
40 andreas 276
	else if (bps == 32)
277
	{
278
		for (sample = i = 0; sample < samples; sample++)
279
		{
280
			for(channel = 0; channel < frame->header.channels; channel++,i++)
281
				u32aobuf[i] = (uint_32)(buffer[channel][sample]);
282
		} 
283
	}
284
 
35 andreas 285
	ao_play(dev, (char *)aobuf, decoded_size);
286
 
33 andreas 287
	if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER)
288
	{
289
		char hv0[255], hv1[32], hv2[32], hv3[32];
35 andreas 290
		double f_tm;
33 andreas 291
 
35 andreas 292
		current_sample += samples;
293
		f_tm = (double)samples / (double)frame->header.sample_rate;
294
		f_el_time += f_tm;
295
		elapsed_seconds = (unsigned)f_el_time;
296
 
297
		if (elapsed_seconds != old_second)
298
		{
56 andreas 299
			if (!playQuiet)
300
			{
301
				sprintf(hv0, "POSITION:%s:%s:%s;", secondsToString(elapsed_seconds, &hv1[0]), secondsToString(total_seconds - elapsed_seconds, &hv2[0]), secondsToString(total_seconds, &hv3[0]));
302
				handleWrite(hv0);
303
			/*	write(s1, hv0, strlen(hv0)); */
304
			}
305
 
35 andreas 306
			old_second = elapsed_seconds;
307
		}
33 andreas 308
	}
309
 
32 andreas 310
	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
311
}
312
 
313
static void sdMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
314
{
315
	if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) 
316
	{
317
		/* save for later */
35 andreas 318
		FLAC__ASSERT(metadata->data.stream_info.total_samples < 0x100000000); /* we can handle < 4 gigasamples */
319
		total_samples = metadata->data.stream_info.total_samples & 0xffffffff;	/* metadata->data.stream_info.total_samples; */
32 andreas 320
		sample_rate = metadata->data.stream_info.sample_rate;
321
		channels = metadata->data.stream_info.channels;
322
		bps = metadata->data.stream_info.bits_per_sample;
33 andreas 323
		total_seconds = (unsigned)total_samples / sample_rate;
32 andreas 324
	}
325
}
326
 
327
static void sdErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void * client_data)
328
{
40 andreas 329
	syslog(LOG_WARNING, "Got error callback: %s", FLAC__StreamDecoderErrorStatusString[status]);
32 andreas 330
}