1 /*
2  * MOC - music on console
3  * Copyright (C) 2004,2005 Damian Pietras <daper@daper.net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  */
11 
12 /*#define DEBUG*/
13 
14 /* Defining OUT_TEST causes the raw audio samples to be written
15  * to the file 'out_test' in the current directory for debugging. */
16 /*#define OUT_TEST*/
17 
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21 
22 #include <assert.h>
23 #include <pthread.h>
24 #include <string.h>
25 #include <errno.h>
26 
27 #ifdef OUT_TEST
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #endif
33 
34 #include "common.h"
35 #include "audio.h"
36 #include "log.h"
37 #include "fifo_buf.h"
38 #include "out_buf.h"
39 #include "options.h"
40 
41 /* Don't play more than this value (in seconds) in one audio_play().
42  * This prevents locking. */
43 #define AUDIO_MAX_PLAY		0.1
44 #define AUDIO_MAX_PLAY_BYTES	32768
45 
46 #ifdef OUT_TEST
47 static int fd;
48 #endif
49 
set_realtime_prio()50 static void set_realtime_prio ()
51 {
52 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
53 	int rc;
54 
55 	if (options_get_int("UseRealtimePriority")) {
56 		struct sched_param param;
57 
58 		param.sched_priority = sched_get_priority_max(SCHED_RR);
59 		rc = pthread_setschedparam (pthread_self (), SCHED_RR, &param);
60 		if (rc != 0)
61 			logit ("Can't set realtime priority: %s", strerror (rc));
62 	}
63 #else
64 	logit ("No sched_get_priority_max() function: "
65 	                  "realtime priority not used.");
66 #endif
67 }
68 
69 /* Reading thread of the buffer. */
read_thread(void * arg)70 static void *read_thread (void *arg)
71 {
72 	struct out_buf *buf = (struct out_buf *)arg;
73 	int audio_dev_closed = 0;
74 
75 	logit ("entering output buffer thread");
76 
77 	set_realtime_prio ();
78 
79 	LOCK (buf->mutex);
80 
81 	while (1) {
82 		int played = 0;
83 		char play_buf[AUDIO_MAX_PLAY_BYTES];
84 		int play_buf_fill;
85 		int play_buf_pos = 0;
86 
87 		if (buf->reset_dev && !audio_dev_closed) {
88 			audio_reset ();
89 			buf->reset_dev = 0;
90 		}
91 
92 		if (buf->stop)
93 			fifo_buf_clear (&buf->buf);
94 
95 		if (buf->free_callback) {
96 			/* unlock the mutex to make calls to out_buf functions
97 			 * possible in the callback */
98 			UNLOCK (buf->mutex);
99 			buf->free_callback ();
100 			LOCK (buf->mutex);
101 		}
102 
103 		debug ("sending the signal");
104 		pthread_cond_broadcast (&buf->ready_cond);
105 
106 		if ((fifo_buf_get_fill(&buf->buf) == 0 || buf->pause || buf->stop)
107 				&& !buf->exit) {
108 			if (buf->pause && !audio_dev_closed) {
109 				logit ("Closing the device due to pause");
110 				audio_close ();
111 				audio_dev_closed = 1;
112 			}
113 
114 			debug ("waiting for something in the buffer");
115 			buf->read_thread_waiting = 1;
116 			pthread_cond_wait (&buf->play_cond, &buf->mutex);
117 			debug ("something appeared in the buffer");
118 		}
119 
120 		buf->read_thread_waiting = 0;
121 
122 		if (audio_dev_closed && !buf->pause) {
123 			logit ("Opening the device again after pause");
124 			if (!audio_open(NULL)) {
125 				logit ("Can't reopen the device! sleeping...");
126 				sleep (1); /* there is no way to exit :( */
127 			}
128 			else
129 				audio_dev_closed = 0;
130 		}
131 
132 		if (fifo_buf_get_fill(&buf->buf) == 0) {
133 			if (buf->exit) {
134 				logit ("exit");
135 				break;
136 			}
137 
138 			logit ("buffer empty");
139 			continue;
140 		}
141 
142 		if (buf->pause) {
143 			logit ("paused");
144 			continue;
145 		}
146 
147 		if (buf->stop) {
148 			logit ("stopped");
149 			continue;
150 		}
151 
152 		if (!audio_dev_closed) {
153 			int audio_bpf;
154 			size_t play_buf_frames;
155 
156 			audio_bpf = audio_get_bpf();
157 			play_buf_frames = MIN(audio_get_bps() * AUDIO_MAX_PLAY,
158 			                      AUDIO_MAX_PLAY_BYTES) / audio_bpf;
159 			play_buf_fill = fifo_buf_get(&buf->buf, play_buf,
160 			                             play_buf_frames * audio_bpf);
161 			UNLOCK (buf->mutex);
162 
163 			debug ("playing %d bytes", play_buf_fill);
164 
165 			while (play_buf_pos < play_buf_fill) {
166 				played = audio_send_pcm (
167 						play_buf + play_buf_pos,
168 						play_buf_fill - play_buf_pos);
169 
170 #ifdef OUT_TEST
171 				write (fd, play_buf + play_buf_pos, played);
172 #endif
173 
174 				play_buf_pos += played;
175 			}
176 
177 			/*logit ("done sending PCM");*/
178 
179 			LOCK (buf->mutex);
180 
181 			/* Update time */
182 			if (play_buf_fill && audio_get_bps())
183 				buf->time += play_buf_fill / (float)audio_get_bps();
184 			buf->hardware_buf_fill = audio_get_buf_fill();
185 		}
186 	}
187 
188 	UNLOCK (buf->mutex);
189 
190 	logit ("exiting");
191 
192 	return NULL;
193 }
194 
195 /* Initialize the buf structure, size is the buffer size. */
out_buf_init(struct out_buf * buf,int size)196 void out_buf_init (struct out_buf *buf, int size)
197 {
198 	int rc;
199 
200 	assert (buf != NULL);
201 	assert (size > 0);
202 
203 	fifo_buf_init (&buf->buf, size);
204 	buf->exit = 0;
205 	buf->pause = 0;
206 	buf->stop = 0;
207 	buf->time = 0.0;
208 	buf->reset_dev = 0;
209 	buf->hardware_buf_fill = 0;
210 	buf->read_thread_waiting = 0;
211 	buf->free_callback = NULL;
212 
213 	pthread_mutex_init (&buf->mutex, NULL);
214 	pthread_cond_init (&buf->play_cond, NULL);
215 	pthread_cond_init (&buf->ready_cond, NULL);
216 
217 #ifdef OUT_TEST
218 	fd = open ("out_test", O_CREAT | O_TRUNC | O_WRONLY, 0600);
219 #endif
220 
221 	rc = pthread_create (&buf->tid, NULL, read_thread, buf);
222 	if (rc != 0)
223 		fatal ("Can't create buffer thread: %s", strerror (rc));
224 }
225 
226 /* Wait for empty buffer, end playing, free resources allocated for the buf
227  * structure.  Can be used only if nothing is played. */
out_buf_destroy(struct out_buf * buf)228 void out_buf_destroy (struct out_buf *buf)
229 {
230 	int rc;
231 
232 	assert (buf != NULL);
233 
234 	LOCK (buf->mutex);
235 	buf->exit = 1;
236 	pthread_cond_signal (&buf->play_cond);
237 	UNLOCK (buf->mutex);
238 
239 	pthread_join (buf->tid, NULL);
240 
241 	/* Let other threads using this buffer know that the state of the
242 	 * buffer has changed. */
243 	LOCK (buf->mutex);
244 	fifo_buf_clear (&buf->buf);
245 	pthread_cond_broadcast (&buf->ready_cond);
246 	UNLOCK (buf->mutex);
247 
248 	fifo_buf_destroy (&buf->buf);
249 	rc = pthread_mutex_destroy (&buf->mutex);
250 	if (rc != 0)
251 		logit ("Destroying buffer mutex failed: %s", strerror (rc));
252 	rc = pthread_cond_destroy (&buf->play_cond);
253 	if (rc != 0)
254 		logit ("Destroying buffer play condition failed: %s", strerror (rc));
255 	rc = pthread_cond_destroy (&buf->ready_cond);
256 	if (rc != 0)
257 		logit ("Destroying buffer ready condition failed: %s", strerror (rc));
258 
259 	logit ("buffer destroyed");
260 
261 #ifdef OUT_TEST
262 	close (fd);
263 #endif
264 }
265 
266 /* Put data at the end of the buffer, return 0 if nothing was put. */
out_buf_put(struct out_buf * buf,const char * data,int size)267 int out_buf_put (struct out_buf *buf, const char *data, int size)
268 {
269 	int pos = 0;
270 
271 	/*logit ("got %d bytes to play", size);*/
272 
273 	while (size) {
274 		int written;
275 
276 		LOCK (buf->mutex);
277 
278 		if (fifo_buf_get_space(&buf->buf) == 0 && !buf->stop) {
279 			/*logit ("buffer full, waiting for the signal");*/
280 			pthread_cond_wait (&buf->ready_cond, &buf->mutex);
281 			/*logit ("buffer ready");*/
282 		}
283 
284 		if (buf->stop) {
285 			logit ("the buffer is stopped, refusing to write to the buffer");
286 			UNLOCK (buf->mutex);
287 			return 0;
288 		}
289 
290 		written = fifo_buf_put (&buf->buf, data + pos, size);
291 
292 		if (written) {
293 			pthread_cond_signal (&buf->play_cond);
294 			size -= written;
295 			pos += written;
296 		}
297 
298 		UNLOCK (buf->mutex);
299 	}
300 
301 	return 1;
302 }
303 
out_buf_pause(struct out_buf * buf)304 void out_buf_pause (struct out_buf *buf)
305 {
306 	LOCK (buf->mutex);
307 	buf->pause = 1;
308 	buf->reset_dev = 1;
309 	UNLOCK (buf->mutex);
310 }
311 
out_buf_unpause(struct out_buf * buf)312 void out_buf_unpause (struct out_buf *buf)
313 {
314 	LOCK (buf->mutex);
315 	buf->pause = 0;
316 	pthread_cond_signal (&buf->play_cond);
317 	UNLOCK (buf->mutex);
318 }
319 
320 /* Stop playing, after that buffer will refuse to play anything and ignore data
321  * sent by buf_put(). */
out_buf_stop(struct out_buf * buf)322 void out_buf_stop (struct out_buf *buf)
323 {
324 	logit ("stopping the buffer");
325 	LOCK (buf->mutex);
326 	buf->stop = 1;
327 	buf->pause = 0;
328 	buf->reset_dev = 1;
329 	logit ("sending signal");
330 	pthread_cond_signal (&buf->play_cond);
331 	logit ("waiting for signal");
332 	pthread_cond_wait (&buf->ready_cond, &buf->mutex);
333 	logit ("done");
334 	UNLOCK (buf->mutex);
335 }
336 
337 /* Reset the buffer state: this can by called ONLY when the buffer is stopped
338  * and buf_put is not used! */
out_buf_reset(struct out_buf * buf)339 void out_buf_reset (struct out_buf *buf)
340 {
341 	logit ("resetting the buffer");
342 
343 	LOCK (buf->mutex);
344 	fifo_buf_clear (&buf->buf);
345 	buf->stop = 0;
346 	buf->pause = 0;
347 	buf->reset_dev = 0;
348 	buf->hardware_buf_fill = 0;
349 	UNLOCK (buf->mutex);
350 }
351 
out_buf_time_set(struct out_buf * buf,const float time)352 void out_buf_time_set (struct out_buf *buf, const float time)
353 {
354 	LOCK (buf->mutex);
355 	buf->time = time;
356 	UNLOCK (buf->mutex);
357 }
358 
359 /* Return the time in the audio which the user is currently hearing.
360  * If unplayed samples still remain in the hardware buffer from the
361  * previous audio then the value returned may be negative and it is
362  * up to the caller to handle this appropriately in the context of
363  * its own processing. */
out_buf_time_get(struct out_buf * buf)364 int out_buf_time_get (struct out_buf *buf)
365 {
366 	int time;
367 	int bps = audio_get_bps ();
368 
369 	LOCK (buf->mutex);
370 	time = buf->time - (bps ? buf->hardware_buf_fill / (float)bps : 0);
371 	UNLOCK (buf->mutex);
372 
373 	return time;
374 }
375 
out_buf_set_free_callback(struct out_buf * buf,out_buf_free_callback callback)376 void out_buf_set_free_callback (struct out_buf *buf,
377 		out_buf_free_callback callback)
378 {
379 	assert (buf != NULL);
380 
381 	LOCK (buf->mutex);
382 	buf->free_callback = callback;
383 	UNLOCK (buf->mutex);
384 }
385 
out_buf_get_free(struct out_buf * buf)386 int out_buf_get_free (struct out_buf *buf)
387 {
388 	int space;
389 
390 	assert (buf != NULL);
391 
392 	LOCK (buf->mutex);
393 	space = fifo_buf_get_space (&buf->buf);
394 	UNLOCK (buf->mutex);
395 
396 	return space;
397 }
398 
out_buf_get_fill(struct out_buf * buf)399 int out_buf_get_fill (struct out_buf *buf)
400 {
401 	int fill;
402 
403 	assert (buf != NULL);
404 
405 	LOCK (buf->mutex);
406 	fill = fifo_buf_get_fill (&buf->buf);
407 	UNLOCK (buf->mutex);
408 
409 	return fill;
410 }
411 
412 /* Wait until the read thread will stop and wait for data to come.
413  * This makes sure that the audio device isn't used (of course only if you
414  * don't put anything in the buffer). */
out_buf_wait(struct out_buf * buf)415 void out_buf_wait (struct out_buf *buf)
416 {
417 	assert (buf != NULL);
418 
419 	logit ("Waiting for read thread to suspend...");
420 
421 	LOCK (buf->mutex);
422 	while (!buf->read_thread_waiting) {
423 		debug ("waiting....");
424 		pthread_cond_wait (&buf->ready_cond, &buf->mutex);
425 	}
426 	UNLOCK (buf->mutex);
427 
428 	logit ("done");
429 }
430