1 /*      $Id: hw_audio.c,v 5.9 2010/04/11 18:50:38 lirc Exp $      */
2 
3 /****************************************************************************
4  ** hw_audio.c **************************************************************
5  ****************************************************************************
6  *
7  * routines for using a IR receiver in microphone input using portaudio library
8  *
9  * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
10  * Copyright (C) 2001, 2002 Pavel Machek <pavel@ucw.cz>
11  * Copyright (C) 2002 Matthias Ringwald <ringwald@inf.ethz.ch>
12  *
13  * Distribute under GPL version 2 or later.
14  *
15  * Using ... hardware ...
16  *
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <limits.h>
28 #include <signal.h>
29 #include <errno.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <sys/ioctl.h>
33 #include <termios.h>
34 #ifdef __APPLE__
35 #include <util.h>
36 #else
37 #include <pty.h>
38 #endif
39 
40 #include "hardware.h"
41 #include "ir_remote.h"
42 #include "lircd.h"
43 #include "receive.h"
44 #include "transmit.h"
45 #include "hw_default.h"
46 
47 static int ptyfd;		/* the pty */
48 
49 /* PortAudio Includes */
50 #include <portaudio.h>
51 
52 #define DEFAULT_SAMPLERATE (48000)
53 #define NUM_CHANNELS           (2)
54 #define PI           (3.141592654)
55 
56 /* Select sample format. */
57 #define PA_SAMPLE_TYPE  paUInt8
58 typedef unsigned char SAMPLE;
59 
60 typedef struct {
61 	int lastFrames[3];
62 	int lastSign;
63 	int pulseSign;
64 	unsigned int lastCount;
65 	lirc_t carrierFreq;
66 	/* position the sine generator is in */
67 	double carrierPos;
68 	/* length of the remaining signal is stored here when the
69 	   callback exits */
70 	double remainingSignal;
71 	/* 1 = pulse, 0 = space */
72 	int signalPhase;
73 	int signaledDone;
74 	int samplesToIgnore;
75 	int samplerate;
76 } paTestData;
77 
78 static PaStream *stream;
79 
80 extern struct ir_remote *repeat_remote;
81 extern struct rbuf rec_buffer;
82 
83 static char ptyName[256];
84 static int master;
85 static int sendPipe[2];		/* signals are written from audio_send
86 				   and read from the callback */
87 static int completedPipe[2];	/* a byte is written here when the
88 				   callback has processed all signals */
89 static int outputLatency;
90 static int inDevicesPrinted = 0;
91 static int outDevicesPrinted = 0;
92 
addCode(lirc_t data)93 static void addCode(lirc_t data)
94 {
95 	write(master, &data, sizeof(lirc_t));
96 }
97 
98 /* This routine will be called by the PortAudio engine when audio is needed.
99 ** It may be called at interrupt level on some machines so don't do anything
100 ** that could mess up the system like calling malloc() or free().
101 */
102 
recordCallback(const void * inputBuffer,void * outputBuffer,__u32 framesPerBuffer,const PaStreamCallbackTimeInfo * outTime,PaStreamCallbackFlags status,void * userData)103 static int recordCallback(const void *inputBuffer, void *outputBuffer, __u32 framesPerBuffer,
104 			  const PaStreamCallbackTimeInfo * outTime, PaStreamCallbackFlags status, void *userData)
105 {
106 	paTestData *data = (paTestData *) userData;
107 	SAMPLE *rptr = (SAMPLE *) inputBuffer;
108 	long i;
109 
110 	SAMPLE *myPtr = rptr;
111 
112 	unsigned int time;
113 	int diff;
114 
115 	SAMPLE *outptr = (SAMPLE *) outputBuffer;
116 	int out;
117 	double currentSignal = data->remainingSignal;
118 	lirc_t signal;
119 
120 	/* Prevent unused variable warnings. */
121 	(void)outTime;
122 
123 	if (status & paOutputUnderflow)
124 		logprintf(LOG_WARNING, "Output underflow %s", hw.device);
125 	if (status & paInputOverflow)
126 		logprintf(LOG_WARNING, "Input overflow %s", hw.device);
127 
128 	for (i = 0; i < framesPerBuffer; i++, myPtr++) {
129 		/* check if we have to ignore this sample */
130 		if (data->samplesToIgnore) {
131 			*myPtr = 128;
132 			data->samplesToIgnore--;
133 		}
134 
135 		/* New Algo */
136 		diff = abs(data->lastFrames[0] - *myPtr);
137 		if (diff > 100) {
138 			if (data->pulseSign == 0) {
139 				/* we got the first signal, this is a PULSE */
140 				if (*myPtr > data->lastFrames[0]) {
141 					data->pulseSign = 1;
142 				} else {
143 					data->pulseSign = -1;
144 				}
145 			}
146 
147 			if (data->lastCount > 0) {
148 				if (*myPtr > data->lastFrames[0] && data->lastSign <= 0) {
149 					/* printf("CHANGE ++ "); */
150 					data->lastSign = 1;
151 
152 					time = data->lastCount * 1000000 / data->samplerate;
153 					if (data->lastSign == data->pulseSign) {
154 						addCode(time);
155 						/* printf("Pause: %d us, %d \n", time, data->lastCount); */
156 					} else {
157 						addCode(time | PULSE_BIT);
158 						/* printf("Pulse: %d us, %d \n", time, data->lastCount); */
159 					}
160 					data->lastCount = 0;
161 				}
162 
163 				else if (*myPtr < data->lastFrames[0] && data->lastSign >= 0) {
164 					/* printf("CHANGE -- "); */
165 					data->lastSign = -1;
166 
167 					time = data->lastCount * 1000000 / data->samplerate;
168 					if (data->lastSign == data->pulseSign) {
169 						/* printf("Pause: %d us, %d \n", time, data->lastCount); */
170 						addCode(time);
171 					} else {
172 						/* printf("Pulse: %d us, %d \n", time, data->lastCount); */
173 						addCode(time | PULSE_BIT);
174 					}
175 					data->lastCount = 0;
176 				}
177 			}
178 		}
179 
180 		if (data->lastCount < 100000) {
181 			data->lastCount++;
182 		}
183 
184 		data->lastFrames[0] = data->lastFrames[1];
185 		data->lastFrames[1] = *myPtr;
186 
187 		/* skip 2. channel */
188 		if (NUM_CHANNELS == 2)
189 			myPtr++;
190 	}
191 
192 	/* generate output */
193 	for (i = 0; i < framesPerBuffer; i++) {
194 		if (currentSignal <= 0.0) {	/* last signal we sent went out */
195 			/* try to read a new signal, non blocking */
196 			if (read(sendPipe[0], &signal, sizeof(signal)) > 0) {
197 				if (data->signaledDone) {
198 					/* first one sent is the
199 					   carrier frequency */
200 					data->carrierFreq = signal;
201 					data->signaledDone = 0;
202 				} else {
203 					/* when a new signal is read,
204 					   add it */
205 					currentSignal += signal;
206 					/* invert the phase */
207 					data->signalPhase = data->signalPhase ? 0 : 1;
208 				}
209 
210 				/* when transmitting, ignore input
211 				   samples for one second */
212 				data->samplesToIgnore = data->samplerate;
213 			} else {
214 				/* no more signals, reset phase */
215 				data->signalPhase = 0;
216 				/* signal that we have written all
217 				   signals */
218 				if (!data->signaledDone) {
219 					char done = 0;
220 					data->signaledDone = 1;
221 					(void)write(completedPipe[1], &done, sizeof(done));
222 				}
223 			}
224 		}
225 
226 		if (currentSignal > 0.0) {
227 			if (data->signalPhase) {
228 				/* write carrier */
229 				out = rint(sin(data->carrierPos / (180.0 / PI)) * 127.0 + 128.0);
230 			} else {
231 				out = 128;
232 			}
233 
234 			/* one channel is inverted, so both channels
235 			   can be used to double the voltage */
236 			*outptr++ = out;
237 			if (NUM_CHANNELS == 2)
238 				*outptr++ = 256 - out;
239 
240 			/* subtract how much of the current signal was sent */
241 			currentSignal -= 1000000.0 / data->samplerate;
242 		} else {
243 			*outptr++ = 128;
244 			if (NUM_CHANNELS == 2)
245 				*outptr++ = 128;
246 		}
247 
248 		/* increase carrier position */
249 		/* carrier frequency is halved */
250 		data->carrierPos += (double)data->carrierFreq / data->samplerate * 360.0 / 2.0;
251 
252 		if (data->carrierPos >= 360.0)
253 			data->carrierPos -= 360.0;
254 	}
255 
256 	/* save how much we still have to write */
257 	data->remainingSignal = currentSignal;
258 
259 	return 0;
260 }
261 
262 /*
263   decoding stuff
264 */
265 
266 #define BUFSIZE 20
267 #define SAMPLE 47999
268 
audio_readdata(lirc_t timeout)269 lirc_t audio_readdata(lirc_t timeout)
270 {
271 	lirc_t data;
272 	int ret;
273 
274 	if (!waitfordata((long)timeout))
275 		return 0;
276 
277 	ret = read(hw.fd, &data, sizeof(data));
278 	if (ret != sizeof(data)) {
279 		LOGPRINTF(1, "error reading from lirc");
280 		LOGPERROR(1, NULL);
281 		raise(SIGTERM);
282 		return 0;
283 	}
284 	return (data);
285 }
286 
audio_send(struct ir_remote * remote,struct ir_ncode * code)287 int audio_send(struct ir_remote *remote, struct ir_ncode *code)
288 {
289 	int length;
290 	lirc_t *signals;
291 	int flags;
292 	char completed;
293 	lirc_t freq;
294 	static lirc_t prevfreq = 0;
295 
296 	if (!init_send(remote, code))
297 		return 0;
298 
299 	length = send_buffer.wptr;
300 	signals = send_buffer.data;
301 
302 	if (length <= 0 || signals == NULL) {
303 		LOGPRINTF(1, "nothing to send");
304 		return 0;
305 	}
306 
307 	/* set completed pipe to non blocking */
308 	flags = fcntl(completedPipe[0], F_GETFL, 0);
309 	fcntl(completedPipe[0], F_SETFL, flags | O_NONBLOCK);
310 
311 	/* remove any unwanted completed bytes */
312 	while (read(completedPipe[0], &completed, sizeof(completed)) == 1) ;
313 
314 	/* set completed pipe to blocking */
315 	fcntl(completedPipe[0], F_SETFL, flags & ~O_NONBLOCK);
316 
317 	/* write carrier frequency */
318 	freq = remote->freq ? remote->freq : DEFAULT_FREQ;
319 	write(sendPipe[1], &freq, sizeof(freq));
320 	if (freq != prevfreq) {
321 		prevfreq = freq;
322 		logprintf(LOG_INFO, "Using carrier frequency %i", freq);
323 	}
324 
325 	/* write signals to sendpipe */
326 	if (write(sendPipe[1], signals, length * sizeof(lirc_t)) == -1) {
327 		logprintf(LOG_ERR, "write failed");
328 		logperror(LOG_ERR, "write()");
329 		return 0;
330 	}
331 
332 	/* wait for the callback to signal us that all signals are written */
333 	read(completedPipe[0], &completed, sizeof(completed));
334 
335 	return 1;
336 }
337 
audio_parsedevicestr(char * api,char * device,int * rate,double * latency)338 static void audio_parsedevicestr(char *api, char *device, int *rate, double *latency)
339 {
340 	int ret;
341 
342 	/* empty device string means default */
343 	if (strlen(hw.device)) {
344 		/* device string is api:device[@rate] or @rate */
345 		ret = sscanf(hw.device, "%1023[^:]:%1023[^@]@%i:%lf", api, device, rate, latency);
346 
347 		if (ret == 2 || *rate <= 0)
348 			*rate = DEFAULT_SAMPLERATE;
349 
350 		if (ret <= 3)
351 			*latency = -1.0;
352 
353 		if (ret >= 2)
354 			return;
355 
356 		/* check for @rate:latency */
357 		ret = sscanf(hw.device, "@%i:%lf", rate, latency);
358 		if (ret >= 1) {
359 			api[0] = 0;
360 			device[0] = 0;
361 			if (*rate <= 0)
362 				*rate = DEFAULT_SAMPLERATE;
363 
364 			if (ret == 1)
365 				*latency = -1.0;
366 
367 			return;
368 		}
369 
370 		logprintf(LOG_ERR,
371 			  "malformed device string %s, syntax is api:device[@rate[:latency]] or @rate[:latency]",
372 			  hw.device);
373 	}
374 
375 	api[0] = 0;
376 	device[0] = 0;
377 	*rate = DEFAULT_SAMPLERATE;
378 	*latency = -1.0;
379 }
380 
audio_choosedevice(PaStreamParameters * streamparameters,int input,char * api,char * device,double latency)381 static void audio_choosedevice(PaStreamParameters * streamparameters, int input, char *api, char *device,
382 			       double latency)
383 {
384 	char *direction = input ? "input" : "output";
385 	int chosendevice = -1;
386 	int i;
387 	int nrdevices = Pa_GetDeviceCount();
388 	const PaDeviceInfo *deviceinfo;
389 	const PaHostApiInfo *hostapiinfo;
390 	const char *devicetype = "custom";
391 	const char *latencytype = "custom";
392 
393 	for (i = 0; i < nrdevices; i++) {
394 		deviceinfo = Pa_GetDeviceInfo(i);
395 
396 		/* check if device can do input or output if
397 		   we need it */
398 		if ((deviceinfo->maxOutputChannels >= NUM_CHANNELS && !input)
399 		    || (deviceinfo->maxInputChannels >= NUM_CHANNELS && input)) {
400 			hostapiinfo = Pa_GetHostApiInfo(deviceinfo->hostApi);
401 			/*check if this matches the custom device */
402 			if (strlen(api) && strlen(device)) {
403 				if (strcmp(api, hostapiinfo->name) == 0 && strcmp(device, deviceinfo->name) == 0)
404 					chosendevice = i;
405 			}
406 
407 			/*allow devices to be printed to the log twice */
408 			/*once for input, once for output */
409 			if ((!inDevicesPrinted && input) || (!outDevicesPrinted && !input)) {
410 				logprintf(LOG_INFO, "Found %s device %i %s:%s", direction, i, hostapiinfo->name,
411 					  deviceinfo->name);
412 			}
413 		}
414 	}
415 
416 	if (input)
417 		inDevicesPrinted = 1;
418 	else
419 		outDevicesPrinted = 1;
420 
421 	if (chosendevice == -1) {
422 		devicetype = "default";
423 
424 		if (strlen(api) && strlen(device))
425 			logprintf(LOG_ERR, "Device %s %s:%s not found", direction, api, device);
426 
427 		if (input)
428 			chosendevice = Pa_GetDefaultInputDevice();
429 		else
430 			chosendevice = Pa_GetDefaultOutputDevice();
431 	}
432 
433 	streamparameters->device = chosendevice;
434 	if (latency < 0.0) {
435 		if (input) {
436 			streamparameters->suggestedLatency = Pa_GetDeviceInfo(chosendevice)->defaultHighInputLatency;
437 			latencytype = "default high input";
438 		} else {
439 			streamparameters->suggestedLatency = Pa_GetDeviceInfo(chosendevice)->defaultHighOutputLatency;
440 			latencytype = "default high output";
441 		}
442 	} else {
443 		streamparameters->suggestedLatency = latency;
444 	}
445 
446 	deviceinfo = Pa_GetDeviceInfo(chosendevice);
447 	hostapiinfo = Pa_GetHostApiInfo(deviceinfo->hostApi);
448 	logprintf(LOG_INFO, "Using %s %s device %i: %s:%s with %s latency %f", devicetype, direction, chosendevice,
449 		  hostapiinfo->name, deviceinfo->name, latencytype, streamparameters->suggestedLatency);
450 }
451 
452 /*
453   interface functions
454 */
455 static paTestData data;
456 
audio_init()457 int audio_init()
458 {
459 
460 	PaStreamParameters inputParameters;
461 	PaStreamParameters outputParameters;
462 	PaError err;
463 	int flags;
464 	struct termios t;
465 	char api[1024];
466 	char device[1024];
467 	double latency;
468 
469 	LOGPRINTF(1, "hw_audio_init()");
470 
471 	//
472 	logprintf(LOG_INFO, "Initializing %s...", hw.device);
473 	init_rec_buffer();
474 	rewind_rec_buffer();
475 
476 	/* new */
477 	data.lastFrames[0] = 128;
478 	data.lastFrames[1] = 128;
479 	data.lastFrames[2] = 128;
480 	data.lastSign = 0;
481 	data.lastCount = 0;
482 	data.pulseSign = 0;
483 	data.carrierPos = 0.0;
484 	data.remainingSignal = 0.0;
485 	data.signalPhase = 0;
486 	data.signaledDone = 1;
487 	data.samplesToIgnore = 0;
488 	data.carrierFreq = DEFAULT_FREQ;
489 
490 	err = Pa_Initialize();
491 	if (err != paNoError)
492 		goto error;
493 
494 	audio_parsedevicestr(api, device, &data.samplerate, &latency);
495 	logprintf(LOG_INFO, "Using samplerate %i", data.samplerate);
496 
497 	/* choose input device */
498 	audio_choosedevice(&inputParameters, 1, api, device, latency);
499 	if (inputParameters.device == paNoDevice) {
500 		logprintf(LOG_ERR, "No input device found");
501 		goto error;
502 	}
503 	inputParameters.channelCount = NUM_CHANNELS;	/* stereo input */
504 	inputParameters.sampleFormat = PA_SAMPLE_TYPE;
505 	inputParameters.hostApiSpecificStreamInfo = NULL;
506 
507 	/* choose output device */
508 	audio_choosedevice(&outputParameters, 0, api, device, latency);
509 	if (outputParameters.device == paNoDevice) {
510 		logprintf(LOG_ERR, "No output device found");
511 		goto error;
512 	}
513 	outputParameters.channelCount = NUM_CHANNELS;	/* stereo output */
514 	outputParameters.sampleFormat = PA_SAMPLE_TYPE;
515 	outputParameters.hostApiSpecificStreamInfo = NULL;
516 
517 	outputLatency = outputParameters.suggestedLatency * 1000000;
518 
519 	/* Record some audio. -------------------------------------------- */
520 	err = Pa_OpenStream(&stream, &inputParameters, &outputParameters, data.samplerate, 512,	/* frames per buffer */
521 			    paPrimeOutputBuffersUsingStreamCallback, recordCallback, &data);
522 
523 	if (err != paNoError)
524 		goto error;
525 
526 	/* open pty */
527 	if (openpty(&master, &ptyfd, ptyName, 0, 0) == -1) {
528 		logprintf(LOG_ERR, "openpty failed");
529 		logperror(LOG_ERR, "openpty()");
530 		goto error;
531 	}
532 
533 	/* regular device file */
534 	if (tcgetattr(master, &t) < 0) {
535 		logprintf(LOG_ERR, "tcgetattr failed");
536 		logperror(LOG_ERR, "tcgetattr()");
537 	}
538 
539 	cfmakeraw(&t);
540 
541 	/* apply file descriptor options */
542 	if (tcsetattr(master, TCSANOW, &t) < 0) {
543 		logprintf(LOG_ERR, "tcsetattr failed");
544 		logperror(LOG_ERR, "tcsetattr()");
545 	}
546 
547 	flags = fcntl(ptyfd, F_GETFL, 0);
548 	if (flags != -1) {
549 		fcntl(ptyfd, F_SETFL, flags | O_NONBLOCK);
550 	}
551 
552 	LOGPRINTF(LOG_INFO, "PTY name: %s", ptyName);
553 
554 	hw.fd = ptyfd;
555 
556 	/* make a pipe for sending signals to the callback */
557 	/* make a pipe for signaling from the callback that everything
558 	   was sent */
559 	if (pipe(sendPipe) == -1 || pipe(completedPipe) == -1) {
560 		logprintf(LOG_ERR, "pipe failed");
561 		logperror(LOG_ERR, "pipe()");
562 	}
563 
564 	/* make the readable end non-blocking */
565 	flags = fcntl(sendPipe[0], F_GETFL, 0);
566 	if (flags != -1) {
567 		fcntl(sendPipe[0], F_SETFL, flags | O_NONBLOCK);
568 	} else {
569 		logprintf(LOG_ERR, "fcntl failed");
570 		logperror(LOG_ERR, "fcntl()");
571 	}
572 
573 	err = Pa_StartStream(stream);
574 	if (err != paNoError)
575 		goto error;
576 
577 	/* wait for portaudio to settle */
578 	usleep(50000);
579 
580 	return (1);
581 
582 error:
583 	Pa_Terminate();
584 	logprintf(LOG_ERR, "an error occured while using the portaudio stream");
585 	logprintf(LOG_ERR, "error number: %d", err);
586 	logprintf(LOG_ERR, "error message: %s", Pa_GetErrorText(err));
587 
588 	return (0);
589 }
590 
audio_deinit(void)591 int audio_deinit(void)
592 {
593 	PaError err;
594 
595 	LOGPRINTF(1, "hw_audio_deinit()");
596 
597 	logprintf(LOG_INFO, "Deinitializing %s...", hw.device);
598 
599 	/* make absolutely sure the full output buffer has played out
600 	   even though portaudio should wait for it, it doesn't always
601 	   happen */
602 	sleep(outputLatency / 1000000);
603 	usleep(outputLatency % 1000000);
604 
605 	/* close port audio */
606 	err = Pa_CloseStream(stream);
607 	if (err != paNoError)
608 		goto error;
609 
610 	Pa_Terminate();
611 
612 	/* wait for terminaton */
613 	usleep(20000);
614 
615 	/* close pty */
616 	close(master);
617 	close(ptyfd);
618 
619 	close(sendPipe[0]);
620 	close(sendPipe[1]);
621 	close(completedPipe[0]);
622 	close(completedPipe[1]);
623 
624 	return 1;
625 
626 error:
627 	Pa_Terminate();
628 	logprintf(LOG_ERR, "an error occured while using the portaudio stream");
629 	logprintf(LOG_ERR, "error number: %d", err);
630 	logprintf(LOG_ERR, "eError message: %s", Pa_GetErrorText(err));
631 	return 0;
632 }
633 
audio_rec(struct ir_remote * remotes)634 char *audio_rec(struct ir_remote *remotes)
635 {
636 	if (!clear_rec_buffer())
637 		return (NULL);
638 	return (decode_all(remotes));
639 }
640 
641 struct hardware hw_audio = {
642 	"",			/* default device */
643 	-1,			/* fd */
644 	LIRC_CAN_REC_MODE2 | LIRC_CAN_SEND_PULSE,	/* features */
645 	LIRC_MODE_PULSE,	/* send_mode */
646 	LIRC_MODE_MODE2,	/* rec_mode */
647 	0,			/* code_length */
648 	audio_init,		/* init_func */
649 	audio_deinit,		/* deinit_func */
650 	audio_send,		/* send_func */
651 	audio_rec,		/* rec_func */
652 	receive_decode,		/* decode_func */
653 	NULL,			/* ioctl_func */
654 	audio_readdata,
655 	"audio"
656 };
657