1 /*
2 * Copyright 2008-2013 Various Authors
3 * Copyright 2004-2006 Timo Hirvonen
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "player.h"
20 #include "buffer.h"
21 #include "input.h"
22 #include "output.h"
23 #include "sf.h"
24 #include "op.h"
25 #include "utils.h"
26 #include "xmalloc.h"
27 #include "debug.h"
28 #include "compiler.h"
29 #include "options.h"
30 #include "mpris.h"
31 #include "cmus.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <pthread.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <sys/time.h>
39 #include <stdarg.h>
40 #include <math.h>
41
42 const char * const player_status_names[] = {
43 "stopped", "playing", "paused", NULL
44 };
45
46 enum producer_status {
47 PS_UNLOADED,
48 PS_STOPPED,
49 PS_PLAYING,
50 PS_PAUSED
51 };
52
53 enum consumer_status {
54 CS_STOPPED,
55 CS_PLAYING,
56 CS_PAUSED
57 };
58
59 /* protects player_info_priv and player_metadata */
60 static pthread_mutex_t player_info_mutex = CMUS_MUTEX_INITIALIZER;
61 struct player_info player_info;
62 char player_metadata[255 * 16 + 1];
63 static struct player_info player_info_priv = {
64 .ti = NULL,
65 .status = PLAYER_STATUS_STOPPED,
66 .pos = 0,
67 .current_bitrate = -1,
68 .buffer_fill = 0,
69 .buffer_size = 0,
70 .error_msg = NULL,
71 .file_changed = 0,
72 .metadata_changed = 0,
73 .status_changed = 0,
74 .position_changed = 0,
75 .buffer_fill_changed = 0,
76 };
77
78 /* continue playing after track is finished? */
79 int player_cont = 1;
80
81 /* continue playing after album is finished? */
82 int player_cont_album = 1;
83
84 /* repeat current track forever? */
85 int player_repeat_current;
86
87 enum replaygain replaygain;
88 int replaygain_limit = 1;
89 double replaygain_preamp = 0.0;
90
91 int soft_vol;
92 int soft_vol_l;
93 int soft_vol_r;
94
95 static sample_format_t buffer_sf;
96 static CHANNEL_MAP(buffer_channel_map);
97
98 static pthread_t producer_thread;
99 static pthread_mutex_t producer_mutex = CMUS_MUTEX_INITIALIZER;
100 static pthread_cond_t producer_playing = CMUS_COND_INITIALIZER;
101 static int producer_running = 1;
102 static enum producer_status producer_status = PS_UNLOADED;
103 static struct input_plugin *ip = NULL;
104
105 static pthread_t consumer_thread;
106 static pthread_mutex_t consumer_mutex = CMUS_MUTEX_INITIALIZER;
107 static pthread_cond_t consumer_playing = CMUS_COND_INITIALIZER;
108 static int consumer_running = 1;
109 static enum consumer_status consumer_status = CS_STOPPED;
110 static unsigned long consumer_pos = 0;
111
112 /* for replay gain and soft vol
113 * usually same as consumer_pos, sometimes more than consumer_pos
114 */
115 static unsigned long scale_pos;
116 static double replaygain_scale = 1.0;
117
118 /* locking {{{ */
119
120 #define player_info_priv_lock() cmus_mutex_lock(&player_info_mutex)
121 #define player_info_priv_unlock() cmus_mutex_unlock(&player_info_mutex)
122
123 #define producer_lock() cmus_mutex_lock(&producer_mutex)
124 #define producer_unlock() cmus_mutex_unlock(&producer_mutex)
125
126 #define consumer_lock() cmus_mutex_lock(&consumer_mutex)
127 #define consumer_unlock() cmus_mutex_unlock(&consumer_mutex)
128
129 #define player_lock() \
130 do { \
131 consumer_lock(); \
132 producer_lock(); \
133 } while (0)
134
135 #define player_unlock() \
136 do { \
137 producer_unlock(); \
138 consumer_unlock(); \
139 } while (0)
140
141 /* locking }}} */
142
reset_buffer(void)143 static void reset_buffer(void)
144 {
145 buffer_reset();
146 consumer_pos = 0;
147 scale_pos = 0;
148 pthread_cond_broadcast(&producer_playing);
149 }
150
set_buffer_sf(void)151 static void set_buffer_sf(void)
152 {
153 buffer_sf = ip_get_sf(ip);
154 ip_get_channel_map(ip, buffer_channel_map);
155
156 /* ip_read converts samples to this format */
157 if (sf_get_channels(buffer_sf) <= 2 && sf_get_bits(buffer_sf) <= 16) {
158 buffer_sf &= SF_RATE_MASK;
159 buffer_sf |= sf_channels(2) | sf_bits(16) | sf_signed(1);
160 buffer_sf |= sf_host_endian();
161 channel_map_init_stereo(buffer_channel_map);
162 }
163 }
164
165 #define SOFT_VOL_SCALE 65536
166
167 /* coefficients for volumes 0..99, for 100 65536 is used
168 * data copied from alsa-lib src/pcm/pcm_softvol.c
169 */
170 static const unsigned short soft_vol_db[100] = {
171 0x0000, 0x0110, 0x011c, 0x012f, 0x013d, 0x0152, 0x0161, 0x0179,
172 0x018a, 0x01a5, 0x01c1, 0x01d5, 0x01f5, 0x020b, 0x022e, 0x0247,
173 0x026e, 0x028a, 0x02b6, 0x02d5, 0x0306, 0x033a, 0x035f, 0x0399,
174 0x03c2, 0x0403, 0x0431, 0x0479, 0x04ac, 0x04fd, 0x0553, 0x058f,
175 0x05ef, 0x0633, 0x069e, 0x06ea, 0x0761, 0x07b5, 0x083a, 0x0898,
176 0x092c, 0x09cb, 0x0a3a, 0x0aeb, 0x0b67, 0x0c2c, 0x0cb6, 0x0d92,
177 0x0e2d, 0x0f21, 0x1027, 0x10de, 0x1202, 0x12cf, 0x1414, 0x14f8,
178 0x1662, 0x1761, 0x18f5, 0x1a11, 0x1bd3, 0x1db4, 0x1f06, 0x211d,
179 0x2297, 0x24ec, 0x2690, 0x292a, 0x2aff, 0x2de5, 0x30fe, 0x332b,
180 0x369f, 0x390d, 0x3ce6, 0x3f9b, 0x43e6, 0x46eb, 0x4bb3, 0x4f11,
181 0x5466, 0x5a18, 0x5e19, 0x6472, 0x68ea, 0x6ffd, 0x74f8, 0x7cdc,
182 0x826a, 0x8b35, 0x9499, 0x9b35, 0xa5ad, 0xad0b, 0xb8b7, 0xc0ee,
183 0xcdf1, 0xd71a, 0xe59c, 0xefd3
184 };
185
scale_sample_int16_t(int16_t * buf,int i,int vol,int swap)186 static inline void scale_sample_int16_t(int16_t *buf, int i, int vol, int swap)
187 {
188 int32_t sample = swap ? (int16_t)swap_uint16(buf[i]) : buf[i];
189
190 if (sample < 0) {
191 sample = (sample * vol - SOFT_VOL_SCALE / 2) / SOFT_VOL_SCALE;
192 if (sample < INT16_MIN)
193 sample = INT16_MIN;
194 } else {
195 sample = (sample * vol + SOFT_VOL_SCALE / 2) / SOFT_VOL_SCALE;
196 if (sample > INT16_MAX)
197 sample = INT16_MAX;
198 }
199 buf[i] = swap ? swap_uint16(sample) : sample;
200 }
201
scale_sample_s24le(int32_t s,int vol)202 static inline int32_t scale_sample_s24le(int32_t s, int vol)
203 {
204 int64_t sample = s;
205 if (sample < 0) {
206 sample = (sample * vol - SOFT_VOL_SCALE / 2) / SOFT_VOL_SCALE;
207 if (sample < -0x800000)
208 sample = -0x800000;
209 } else {
210 sample = (sample * vol + SOFT_VOL_SCALE / 2) / SOFT_VOL_SCALE;
211 if (sample > 0x7fffff)
212 sample = 0x7fffff;
213 }
214 return sample;
215 }
216
scale_sample_int32_t(int32_t * buf,int i,int vol,int swap)217 static inline void scale_sample_int32_t(int32_t *buf, int i, int vol, int swap)
218 {
219 int64_t sample = swap ? (int32_t)swap_uint32(buf[i]) : buf[i];
220
221 if (sample < 0) {
222 sample = (sample * vol - SOFT_VOL_SCALE / 2) / SOFT_VOL_SCALE;
223 if (sample < INT32_MIN)
224 sample = INT32_MIN;
225 } else {
226 sample = (sample * vol + SOFT_VOL_SCALE / 2) / SOFT_VOL_SCALE;
227 if (sample > INT32_MAX)
228 sample = INT32_MAX;
229 }
230 buf[i] = swap ? swap_uint32(sample) : sample;
231 }
232
sf_need_swap(sample_format_t sf)233 static inline int sf_need_swap(sample_format_t sf)
234 {
235 #ifdef WORDS_BIGENDIAN
236 return !sf_get_bigendian(sf);
237 #else
238 return sf_get_bigendian(sf);
239 #endif
240 }
241
242 #define SCALE_SAMPLES(TYPE, buffer, count, l, r, swap) \
243 { \
244 const int frames = count / sizeof(TYPE) / 2; \
245 TYPE *buf = (void *) buffer; \
246 int i; \
247 /* avoid underflowing -32768 to 32767 when scale is 65536 */ \
248 if (l != SOFT_VOL_SCALE && r != SOFT_VOL_SCALE) { \
249 for (i = 0; i < frames; i++) { \
250 scale_sample_##TYPE(buf, i * 2, l, swap); \
251 scale_sample_##TYPE(buf, i * 2 + 1, r, swap); \
252 } \
253 } else if (l != SOFT_VOL_SCALE) { \
254 for (i = 0; i < frames; i++) \
255 scale_sample_##TYPE(buf, i * 2, l, swap); \
256 } else if (r != SOFT_VOL_SCALE) { \
257 for (i = 0; i < frames; i++) \
258 scale_sample_##TYPE(buf, i * 2 + 1, r, swap); \
259 } \
260 }
261
read_s24le(const char * buf)262 static inline int32_t read_s24le(const char *buf)
263 {
264 const unsigned char *b = (const unsigned char *) buf;
265 return b[0] | (b[1] << 8) | (((const signed char *) buf)[2] << 16);
266 }
267
write_s24le(char * buf,int32_t x)268 static inline void write_s24le(char *buf, int32_t x)
269 {
270 unsigned char *b = (unsigned char *) buf;
271 b[0] = x;
272 b[1] = x >> 8;
273 b[2] = x >> 16;
274 }
275
scale_samples_s24le(char * buf,unsigned int count,int l,int r)276 static void scale_samples_s24le(char *buf, unsigned int count, int l, int r)
277 {
278 int frames = count / 3 / 2;
279 if (l != SOFT_VOL_SCALE && r != SOFT_VOL_SCALE) {
280 while (frames--) {
281 write_s24le(buf, scale_sample_s24le(read_s24le(buf), l));
282 buf += 3;
283 write_s24le(buf, scale_sample_s24le(read_s24le(buf), r));
284 buf += 3;
285 }
286 } else if (l != SOFT_VOL_SCALE) {
287 while (frames--) {
288 write_s24le(buf, scale_sample_s24le(read_s24le(buf), l));
289 buf += 3 * 2;
290 }
291 } else if (r != SOFT_VOL_SCALE) {
292 buf += 3;
293 while (frames--) {
294 write_s24le(buf, scale_sample_s24le(read_s24le(buf), r));
295 buf += 3 * 2;
296 }
297 }
298 }
299
scale_samples(char * buffer,unsigned int * countp)300 static void scale_samples(char *buffer, unsigned int *countp)
301 {
302 unsigned int count = *countp;
303 int ch, bits, l, r;
304
305 BUG_ON(scale_pos < consumer_pos);
306
307 if (consumer_pos != scale_pos) {
308 unsigned int offs = scale_pos - consumer_pos;
309
310 if (offs >= count)
311 return;
312 buffer += offs;
313 count -= offs;
314 }
315 scale_pos += count;
316
317 if (replaygain_scale == 1.0 && soft_vol_l == 100 && soft_vol_r == 100)
318 return;
319
320 ch = sf_get_channels(buffer_sf);
321 bits = sf_get_bits(buffer_sf);
322 if (ch != 2 || (bits != 16 && bits != 24 && bits != 32))
323 return;
324
325 l = SOFT_VOL_SCALE;
326 r = SOFT_VOL_SCALE;
327 if (soft_vol && soft_vol_l != 100)
328 l = soft_vol_db[soft_vol_l];
329 if (soft_vol && soft_vol_r != 100)
330 r = soft_vol_db[soft_vol_r];
331
332 l *= replaygain_scale;
333 r *= replaygain_scale;
334
335 switch (bits) {
336 case 16:
337 SCALE_SAMPLES(int16_t, buffer, count, l, r, sf_need_swap(buffer_sf));
338 break;
339 case 24:
340 if (likely(!sf_get_bigendian(buffer_sf)))
341 scale_samples_s24le(buffer, count, l, r);
342 break;
343 case 32:
344 SCALE_SAMPLES(int32_t, buffer, count, l, r, sf_need_swap(buffer_sf));
345 break;
346 }
347 }
348
update_rg_scale(void)349 static void update_rg_scale(void)
350 {
351 double gain, peak, db, scale, limit;
352
353 replaygain_scale = 1.0;
354 if (!player_info_priv.ti || !replaygain)
355 return;
356
357 if (replaygain == RG_TRACK || replaygain == RG_TRACK_PREFERRED) {
358 gain = player_info_priv.ti->rg_track_gain;
359 peak = player_info_priv.ti->rg_track_peak;
360 } else {
361 gain = player_info_priv.ti->rg_album_gain;
362 peak = player_info_priv.ti->rg_album_peak;
363 }
364
365 if (isnan(gain)) {
366 if (replaygain == RG_TRACK_PREFERRED) {
367 gain = player_info_priv.ti->rg_album_gain;
368 peak = player_info_priv.ti->rg_album_peak;
369 } else if (replaygain == RG_ALBUM_PREFERRED) {
370 gain = player_info_priv.ti->rg_track_gain;
371 peak = player_info_priv.ti->rg_track_peak;
372 }
373 }
374
375 if (isnan(gain)) {
376 d_print("gain not available\n");
377 return;
378 }
379 if (isnan(peak)) {
380 d_print("peak not available, defaulting to 1\n");
381 peak = 1;
382 }
383 if (peak < 0.05) {
384 d_print("peak (%g) is too small\n", peak);
385 return;
386 }
387
388 db = replaygain_preamp + gain;
389
390 scale = pow(10.0, db / 20.0);
391 replaygain_scale = scale;
392 limit = 1.0 / peak;
393 if (replaygain_limit && !isnan(peak)) {
394 if (replaygain_scale > limit)
395 replaygain_scale = limit;
396 }
397
398 d_print("gain = %f, peak = %f, db = %f, scale = %f, limit = %f, replaygain_scale = %f\n",
399 gain, peak, db, scale, limit, replaygain_scale);
400 }
401
buffer_second_size(void)402 static inline unsigned int buffer_second_size(void)
403 {
404 return sf_get_second_size(buffer_sf);
405 }
406
407 /* updating player status {{{ */
408
_file_changed(struct track_info * ti)409 static inline void _file_changed(struct track_info *ti)
410 {
411 player_info_priv_lock();
412 if (player_info_priv.ti)
413 track_info_unref(player_info_priv.ti);
414
415 player_info_priv.ti = ti;
416 update_rg_scale();
417 player_metadata[0] = 0;
418 player_info_priv.file_changed = 1;
419 player_info_priv_unlock();
420 }
421
file_changed(struct track_info * ti)422 static inline void file_changed(struct track_info *ti)
423 {
424 if (ti) {
425 d_print("file: %s\n", ti->filename);
426 } else {
427 d_print("unloaded\n");
428 }
429 _file_changed(ti);
430 }
431
metadata_changed(void)432 static inline void metadata_changed(void)
433 {
434 struct keyval *comments;
435 int rc;
436
437 player_info_priv_lock();
438 if (ip_get_metadata(ip)) {
439 d_print("metadata changed: %s\n", ip_get_metadata(ip));
440 memcpy(player_metadata, ip_get_metadata(ip), 255 * 16 + 1);
441 }
442
443 rc = ip_read_comments(ip, &comments);
444 if (!rc) {
445 if (player_info_priv.ti->comments)
446 keyvals_free(player_info_priv.ti->comments);
447 track_info_set_comments(player_info_priv.ti, comments);
448 }
449
450 player_info_priv.metadata_changed = 1;
451 player_info_priv_unlock();
452 }
453
player_error(const char * msg)454 static void player_error(const char *msg)
455 {
456 player_info_priv_lock();
457 player_info_priv.status = (enum player_status)consumer_status;
458 player_info_priv.pos = 0;
459 player_info_priv.current_bitrate = -1;
460 player_info_priv.buffer_fill = buffer_get_filled_chunks();
461 player_info_priv.buffer_size = buffer_nr_chunks;
462 player_info_priv.status_changed = 1;
463
464 free(player_info_priv.error_msg);
465 player_info_priv.error_msg = xstrdup(msg);
466 player_info_priv_unlock();
467
468 d_print("ERROR: '%s'\n", msg);
469 }
470
player_ip_error(int rc,const char * format,...)471 static void CMUS_FORMAT(2, 3) player_ip_error(int rc, const char *format, ...)
472 {
473 char buffer[1024];
474 va_list ap;
475 char *msg;
476 int save = errno;
477
478 va_start(ap, format);
479 vsnprintf(buffer, sizeof(buffer), format, ap);
480 va_end(ap);
481
482 errno = save;
483 msg = ip_get_error_msg(ip, rc, buffer);
484 player_error(msg);
485 free(msg);
486 }
487
player_op_error(int rc,const char * format,...)488 static void CMUS_FORMAT(2, 3) player_op_error(int rc, const char *format, ...)
489 {
490 char buffer[1024];
491 va_list ap;
492 char *msg;
493 int save = errno;
494
495 va_start(ap, format);
496 vsnprintf(buffer, sizeof(buffer), format, ap);
497 va_end(ap);
498
499 errno = save;
500 msg = op_get_error_msg(rc, buffer);
501 player_error(msg);
502 free(msg);
503 }
504
505 /*
506 * buffer-fill changed
507 */
_producer_buffer_fill_update(void)508 static void _producer_buffer_fill_update(void)
509 {
510 int fill;
511
512 player_info_priv_lock();
513 fill = buffer_get_filled_chunks();
514 if (fill != player_info_priv.buffer_fill) {
515 /* d_print("\n"); */
516 player_info_priv.buffer_fill = fill;
517 player_info_priv.buffer_fill_changed = 1;
518 }
519 player_info_priv_unlock();
520 }
521
522 /*
523 * playing position changed
524 */
_consumer_position_update(void)525 static void _consumer_position_update(void)
526 {
527 static unsigned int old_pos = -1;
528 unsigned int pos = 0;
529 long bitrate;
530
531 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED)
532 pos = consumer_pos / buffer_second_size();
533 if (pos != old_pos) {
534 old_pos = pos;
535
536 player_info_priv_lock();
537 player_info_priv.pos = pos;
538
539 if (show_current_bitrate) {
540 bitrate = ip_current_bitrate(ip);
541 if (bitrate != -1)
542 player_info_priv.current_bitrate = bitrate;
543 }
544 player_info_priv.position_changed = 1;
545 player_info_priv_unlock();
546 }
547 }
548
549 /*
550 * something big happened (stopped/paused/unpaused...)
551 */
_player_status_changed(void)552 static void _player_status_changed(void)
553 {
554 unsigned int pos = 0;
555
556 /* d_print("\n"); */
557 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED)
558 pos = consumer_pos / buffer_second_size();
559
560 player_info_priv_lock();
561 player_info_priv.status = (enum player_status)consumer_status;
562 player_info_priv.pos = pos;
563 player_info_priv.current_bitrate = -1;
564 player_info_priv.buffer_fill = buffer_get_filled_chunks();
565 player_info_priv.buffer_size = buffer_nr_chunks;
566 player_info_priv.status_changed = 1;
567 player_info_priv_unlock();
568 }
569
570 /* updating player status }}} */
571
_prebuffer(void)572 static void _prebuffer(void)
573 {
574 int limit_chunks;
575
576 BUG_ON(producer_status != PS_PLAYING);
577 if (ip_is_remote(ip)) {
578 limit_chunks = buffer_nr_chunks;
579 } else {
580 int limit_ms, limit_size;
581
582 limit_ms = 250;
583 limit_size = limit_ms * buffer_second_size() / 1000;
584 limit_chunks = limit_size / CHUNK_SIZE;
585 if (limit_chunks < 1)
586 limit_chunks = 1;
587 }
588 while (1) {
589 int nr_read, size, filled;
590 char *wpos;
591
592 filled = buffer_get_filled_chunks();
593 /* d_print("PREBUF: %2d / %2d\n", filled, limit_chunks); */
594
595 /* not fatal */
596 //BUG_ON(filled > limit_chunks);
597
598 if (filled >= limit_chunks)
599 break;
600
601 size = buffer_get_wpos(&wpos);
602 nr_read = ip_read(ip, wpos, size);
603 if (nr_read < 0) {
604 if (nr_read == -1 && errno == EAGAIN)
605 continue;
606 player_ip_error(nr_read, "reading file %s", ip_get_filename(ip));
607 /* ip_read sets eof */
608 nr_read = 0;
609 }
610 if (ip_metadata_changed(ip))
611 metadata_changed();
612
613 /* buffer_fill with 0 count marks current chunk filled */
614 buffer_fill(nr_read);
615
616 _producer_buffer_fill_update();
617 if (nr_read == 0) {
618 /* EOF */
619 break;
620 }
621 }
622 }
623
624 /* setting producer status {{{ */
625
_producer_status_update(enum producer_status status)626 static void _producer_status_update(enum producer_status status)
627 {
628 producer_status = status;
629 pthread_cond_broadcast(&producer_playing);
630 }
631
_producer_play(void)632 static void _producer_play(void)
633 {
634 if (producer_status == PS_UNLOADED) {
635 struct track_info *ti;
636
637 if ((ti = cmus_get_next_track())) {
638 int rc;
639
640 ip = ip_new(ti->filename);
641 rc = ip_open(ip);
642 if (rc) {
643 player_ip_error(rc, "opening file `%s'", ti->filename);
644 ip_delete(ip);
645 track_info_unref(ti);
646 file_changed(NULL);
647 } else {
648 ip_setup(ip);
649 _producer_status_update(PS_PLAYING);
650 file_changed(ti);
651 }
652 }
653 } else if (producer_status == PS_PLAYING) {
654 if (ip_seek(ip, 0.0) == 0) {
655 reset_buffer();
656 }
657 } else if (producer_status == PS_STOPPED) {
658 int rc;
659
660 rc = ip_open(ip);
661 if (rc) {
662 player_ip_error(rc, "opening file `%s'", ip_get_filename(ip));
663 ip_delete(ip);
664 _producer_status_update(PS_UNLOADED);
665 } else {
666 ip_setup(ip);
667 _producer_status_update(PS_PLAYING);
668 }
669 } else if (producer_status == PS_PAUSED) {
670 _producer_status_update(PS_PLAYING);
671 }
672 }
673
_producer_stop(void)674 static void _producer_stop(void)
675 {
676 if (producer_status == PS_PLAYING || producer_status == PS_PAUSED) {
677 ip_close(ip);
678 _producer_status_update(PS_STOPPED);
679 reset_buffer();
680 }
681 }
682
_producer_unload(void)683 static void _producer_unload(void)
684 {
685 _producer_stop();
686 if (producer_status == PS_STOPPED) {
687 ip_delete(ip);
688 _producer_status_update(PS_UNLOADED);
689 }
690 }
691
_producer_pause(void)692 static void _producer_pause(void)
693 {
694 if (producer_status == PS_PLAYING) {
695 _producer_status_update(PS_PAUSED);
696 } else if (producer_status == PS_PAUSED) {
697 _producer_status_update(PS_PLAYING);
698 }
699 }
700
_producer_set_file(struct track_info * ti)701 static void _producer_set_file(struct track_info *ti)
702 {
703 _producer_unload();
704 ip = ip_new(ti->filename);
705 _producer_status_update(PS_STOPPED);
706 file_changed(ti);
707 }
708
709 /* setting producer status }}} */
710
711 /* setting consumer status {{{ */
712
_consumer_status_update(enum consumer_status status)713 static void _consumer_status_update(enum consumer_status status)
714 {
715 consumer_status = status;
716 pthread_cond_broadcast(&consumer_playing);
717 }
718
_consumer_play(void)719 static void _consumer_play(void)
720 {
721 if (consumer_status == CS_PLAYING) {
722 op_drop();
723 } else if (consumer_status == CS_STOPPED) {
724 int rc;
725
726 set_buffer_sf();
727 rc = op_open(buffer_sf, buffer_channel_map);
728 if (rc) {
729 player_op_error(rc, "opening audio device");
730 } else {
731 _consumer_status_update(CS_PLAYING);
732 }
733 } else if (consumer_status == CS_PAUSED) {
734 op_unpause();
735 _consumer_status_update(CS_PLAYING);
736 }
737 }
738
_consumer_drain_and_stop(void)739 static void _consumer_drain_and_stop(void)
740 {
741 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED) {
742 op_close();
743 _consumer_status_update(CS_STOPPED);
744 }
745 }
746
_consumer_stop(void)747 static void _consumer_stop(void)
748 {
749 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED) {
750 op_drop();
751 op_close();
752 _consumer_status_update(CS_STOPPED);
753 }
754 }
755
_consumer_pause(void)756 static void _consumer_pause(void)
757 {
758 if (consumer_status == CS_PLAYING) {
759 op_pause();
760 _consumer_status_update(CS_PAUSED);
761 } else if (consumer_status == CS_PAUSED) {
762 op_unpause();
763 _consumer_status_update(CS_PLAYING);
764 }
765 }
766
767 /* setting consumer status }}} */
768
change_sf(int drop)769 static int change_sf(int drop)
770 {
771 int old_sf = buffer_sf;
772 CHANNEL_MAP(old_channel_map);
773 channel_map_copy(old_channel_map, buffer_channel_map);
774
775 set_buffer_sf();
776 if (buffer_sf != old_sf || !channel_map_equal(buffer_channel_map, old_channel_map, sf_get_channels(buffer_sf))) {
777 /* reopen */
778 int rc;
779
780 if (drop)
781 op_drop();
782 op_close();
783 rc = op_open(buffer_sf, buffer_channel_map);
784 if (rc) {
785 player_op_error(rc, "opening audio device");
786 _consumer_status_update(CS_STOPPED);
787 _producer_stop();
788 return rc;
789 }
790 } else if (consumer_status == CS_PAUSED) {
791 op_drop();
792 op_unpause();
793 }
794 _consumer_status_update(CS_PLAYING);
795 return 0;
796 }
797
_consumer_handle_eof(void)798 static void _consumer_handle_eof(void)
799 {
800 struct track_info *ti;
801
802 if (ip_is_remote(ip)) {
803 _producer_stop();
804 _consumer_drain_and_stop();
805 player_error("lost connection");
806 return;
807 }
808
809 if (player_info_priv.ti)
810 player_info_priv.ti->play_count++;
811
812 if (player_repeat_current) {
813 if (player_cont) {
814 ip_seek(ip, 0);
815 reset_buffer();
816 } else {
817 _producer_stop();
818 _consumer_drain_and_stop();
819 }
820 _player_status_changed();
821 return;
822 }
823
824 if ((ti = cmus_get_next_track())) {
825 _producer_unload();
826 ip = ip_new(ti->filename);
827 _producer_status_update(PS_STOPPED);
828 /* PS_STOPPED, CS_PLAYING */
829 if (player_cont && (player_cont_album == 1 || strcmp(player_info_priv.ti->album,ti->album) == 0)) {
830 _producer_play();
831 if (producer_status == PS_UNLOADED) {
832 _consumer_stop();
833 track_info_unref(ti);
834 file_changed(NULL);
835 } else {
836 /* PS_PLAYING */
837 file_changed(ti);
838 if (!change_sf(0))
839 _prebuffer();
840 }
841 } else {
842 _consumer_drain_and_stop();
843 file_changed(ti);
844 }
845 } else {
846 _producer_unload();
847 _consumer_drain_and_stop();
848 file_changed(NULL);
849 }
850 _player_status_changed();
851 }
852
consumer_loop(void * arg)853 static void *consumer_loop(void *arg)
854 {
855 while (1) {
856 int rc, space;
857 int size;
858 char *rpos;
859
860 consumer_lock();
861 if (!consumer_running)
862 break;
863
864 if (consumer_status == CS_PAUSED || consumer_status == CS_STOPPED) {
865 pthread_cond_wait(&consumer_playing, &consumer_mutex);
866 consumer_unlock();
867 continue;
868 }
869 space = op_buffer_space();
870 if (space < 0) {
871 d_print("op_buffer_space returned %d %s\n", space,
872 space == -1 ? strerror(errno) : "");
873
874 /* try to reopen */
875 op_close();
876 _consumer_status_update(CS_STOPPED);
877 _consumer_play();
878
879 consumer_unlock();
880 continue;
881 }
882 /* d_print("BS: %6d %3d\n", space, space * 1000 / (44100 * 2 * 2)); */
883
884 while (1) {
885 if (space == 0) {
886 _consumer_position_update();
887 consumer_unlock();
888 ms_sleep(25);
889 break;
890 }
891 size = buffer_get_rpos(&rpos);
892 if (size == 0) {
893 producer_lock();
894 if (producer_status != PS_PLAYING) {
895 producer_unlock();
896 consumer_unlock();
897 break;
898 }
899 /* must recheck rpos */
900 size = buffer_get_rpos(&rpos);
901 if (size == 0) {
902 /* OK. now it's safe to check if we are at EOF */
903 if (ip_eof(ip)) {
904 /* EOF */
905 _consumer_handle_eof();
906 producer_unlock();
907 consumer_unlock();
908 break;
909 } else {
910 /* possible underrun */
911 producer_unlock();
912 _consumer_position_update();
913 consumer_unlock();
914 /* d_print("possible underrun\n"); */
915 ms_sleep(10);
916 break;
917 }
918 }
919
920 /* player_buffer and ip.eof were inconsistent */
921 producer_unlock();
922 }
923 if (size > space)
924 size = space;
925 if (soft_vol || replaygain)
926 scale_samples(rpos, (unsigned int *)&size);
927 rc = op_write(rpos, size);
928 if (rc < 0) {
929 d_print("op_write returned %d %s\n", rc,
930 rc == -1 ? strerror(errno) : "");
931
932 /* try to reopen */
933 op_close();
934 _consumer_status_update(CS_STOPPED);
935 _consumer_play();
936
937 consumer_unlock();
938 break;
939 }
940 buffer_consume(rc);
941 consumer_pos += rc;
942 space -= rc;
943 }
944 }
945 _consumer_stop();
946 consumer_unlock();
947 return NULL;
948 }
949
producer_loop(void * arg)950 static void *producer_loop(void *arg)
951 {
952 while (1) {
953 /* number of chunks to fill
954 * too big => seeking is slow
955 * too small => underruns?
956 */
957 const int chunks = 1;
958 int size, nr_read, i;
959 char *wpos;
960
961 producer_lock();
962 if (!producer_running)
963 break;
964
965 if (producer_status == PS_UNLOADED ||
966 producer_status == PS_PAUSED ||
967 producer_status == PS_STOPPED || ip_eof(ip)) {
968 pthread_cond_wait(&producer_playing, &producer_mutex);
969 producer_unlock();
970 continue;
971 }
972 for (i = 0; ; i++) {
973 size = buffer_get_wpos(&wpos);
974 if (size == 0) {
975 /* buffer is full */
976 producer_unlock();
977 ms_sleep(50);
978 break;
979 }
980 nr_read = ip_read(ip, wpos, size);
981 if (nr_read < 0) {
982 if (nr_read != -1 || errno != EAGAIN) {
983 player_ip_error(nr_read, "reading file %s",
984 ip_get_filename(ip));
985 /* ip_read sets eof */
986 nr_read = 0;
987 } else {
988 producer_unlock();
989 ms_sleep(50);
990 break;
991 }
992 }
993 if (ip_metadata_changed(ip))
994 metadata_changed();
995
996 /* buffer_fill with 0 count marks current chunk filled */
997 buffer_fill(nr_read);
998 if (nr_read == 0) {
999 /* consumer handles EOF */
1000 producer_unlock();
1001 ms_sleep(50);
1002 break;
1003 }
1004 if (i == chunks) {
1005 producer_unlock();
1006 /* don't sleep! */
1007 break;
1008 }
1009 }
1010 _producer_buffer_fill_update();
1011 }
1012 _producer_unload();
1013 producer_unlock();
1014 return NULL;
1015 }
1016
player_init(void)1017 void player_init(void)
1018 {
1019 int rc;
1020 #ifdef REALTIME_SCHEDULING
1021 pthread_attr_t attr;
1022 #endif
1023 pthread_attr_t *attrp = NULL;
1024
1025 /* 1 s is 176400 B (0.168 MB)
1026 * 10 s is 1.68 MB
1027 */
1028 buffer_nr_chunks = 10 * 44100 * 16 / 8 * 2 / CHUNK_SIZE;
1029 buffer_init();
1030
1031 #ifdef REALTIME_SCHEDULING
1032 rc = pthread_attr_init(&attr);
1033 BUG_ON(rc);
1034 rc = pthread_attr_setschedpolicy(&attr, SCHED_RR);
1035 if (rc) {
1036 d_print("could not set real-time scheduling priority: %s\n", strerror(rc));
1037 } else {
1038 struct sched_param param;
1039
1040 d_print("using real-time scheduling\n");
1041 param.sched_priority = sched_get_priority_max(SCHED_RR);
1042 d_print("setting priority to %d\n", param.sched_priority);
1043 rc = pthread_attr_setschedparam(&attr, ¶m);
1044 BUG_ON(rc);
1045 attrp = &attr;
1046 }
1047 #endif
1048
1049 rc = pthread_create(&producer_thread, NULL, producer_loop, NULL);
1050 BUG_ON(rc);
1051
1052 rc = pthread_create(&consumer_thread, attrp, consumer_loop, NULL);
1053 if (rc && attrp) {
1054 d_print("could not create thread using real-time scheduling: %s\n", strerror(rc));
1055 rc = pthread_create(&consumer_thread, NULL, consumer_loop, NULL);
1056 }
1057 BUG_ON(rc);
1058
1059 /* update player_info_priv.cont etc. */
1060 player_lock();
1061 _player_status_changed();
1062 player_unlock();
1063 }
1064
player_exit(void)1065 void player_exit(void)
1066 {
1067 int rc;
1068
1069 player_lock();
1070 consumer_running = 0;
1071 pthread_cond_broadcast(&consumer_playing);
1072 producer_running = 0;
1073 pthread_cond_broadcast(&producer_playing);
1074 player_unlock();
1075
1076 rc = pthread_join(consumer_thread, NULL);
1077 BUG_ON(rc);
1078 rc = pthread_join(producer_thread, NULL);
1079 BUG_ON(rc);
1080 buffer_free();
1081 }
1082
player_stop(void)1083 void player_stop(void)
1084 {
1085 player_lock();
1086 _consumer_stop();
1087 _producer_stop();
1088 _player_status_changed();
1089 player_unlock();
1090 }
1091
player_play(void)1092 void player_play(void)
1093 {
1094 int prebuffer;
1095
1096 player_lock();
1097 if (producer_status == PS_PLAYING && ip_is_remote(ip)) {
1098 /* seeking not allowed */
1099 player_unlock();
1100 return;
1101 }
1102 prebuffer = consumer_status == CS_STOPPED;
1103 _producer_play();
1104 if (producer_status == PS_PLAYING) {
1105 _consumer_play();
1106 if (consumer_status != CS_PLAYING)
1107 _producer_stop();
1108 } else {
1109 _consumer_stop();
1110 }
1111 _player_status_changed();
1112 if (consumer_status == CS_PLAYING && prebuffer)
1113 _prebuffer();
1114 player_unlock();
1115 }
1116
player_pause(void)1117 void player_pause(void)
1118 {
1119 if (ip && ip_is_remote(ip) && consumer_status == CS_PLAYING) {
1120 /* pausing not allowed */
1121 player_stop();
1122 return;
1123 }
1124 player_lock();
1125
1126 if (consumer_status == CS_STOPPED) {
1127 _producer_play();
1128 if (producer_status == PS_PLAYING) {
1129 _consumer_play();
1130 if (consumer_status != CS_PLAYING)
1131 _producer_stop();
1132 }
1133 _player_status_changed();
1134 if (consumer_status == CS_PLAYING)
1135 _prebuffer();
1136 player_unlock();
1137 return;
1138 }
1139
1140 _producer_pause();
1141 _consumer_pause();
1142 _player_status_changed();
1143 player_unlock();
1144 }
1145
player_pause_playback(void)1146 void player_pause_playback(void)
1147 {
1148 if (consumer_status == CS_PLAYING)
1149 player_pause();
1150 }
1151
player_set_file(struct track_info * ti)1152 void player_set_file(struct track_info *ti)
1153 {
1154 player_lock();
1155 _producer_set_file(ti);
1156 if (producer_status == PS_UNLOADED) {
1157 _consumer_stop();
1158 goto out;
1159 }
1160
1161 /* PS_STOPPED */
1162 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED) {
1163 op_drop();
1164 _producer_play();
1165 if (producer_status == PS_UNLOADED) {
1166 _consumer_stop();
1167 goto out;
1168 }
1169 change_sf(1);
1170 }
1171 out:
1172 _player_status_changed();
1173 if (producer_status == PS_PLAYING)
1174 _prebuffer();
1175 player_unlock();
1176 }
1177
player_play_file(struct track_info * ti)1178 void player_play_file(struct track_info *ti)
1179 {
1180 player_lock();
1181 _producer_set_file(ti);
1182 if (producer_status == PS_UNLOADED) {
1183 _consumer_stop();
1184 goto out;
1185 }
1186
1187 /* PS_STOPPED */
1188 _producer_play();
1189
1190 /* PS_UNLOADED,PS_PLAYING */
1191 if (producer_status == PS_UNLOADED) {
1192 _consumer_stop();
1193 goto out;
1194 }
1195
1196 /* PS_PLAYING */
1197 if (consumer_status == CS_STOPPED) {
1198 _consumer_play();
1199 if (consumer_status == CS_STOPPED)
1200 _producer_stop();
1201 } else {
1202 op_drop();
1203 change_sf(1);
1204 }
1205 out:
1206 _player_status_changed();
1207 if (producer_status == PS_PLAYING)
1208 _prebuffer();
1209 player_unlock();
1210 }
1211
player_file_changed(struct track_info * ti)1212 void player_file_changed(struct track_info *ti)
1213 {
1214 _file_changed(ti);
1215 }
1216
player_seek(double offset,int relative,int start_playing)1217 void player_seek(double offset, int relative, int start_playing)
1218 {
1219 int stopped = 0;
1220 player_lock();
1221 if (consumer_status == CS_STOPPED) {
1222 stopped = 1;
1223 _producer_play();
1224 if (producer_status == PS_PLAYING) {
1225 _consumer_play();
1226 if (consumer_status != CS_PLAYING) {
1227 _producer_stop();
1228 player_unlock();
1229 return;
1230 } else
1231 _player_status_changed();
1232 }
1233 }
1234 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED) {
1235 double pos, duration, new_pos;
1236 int rc;
1237
1238 pos = (double)consumer_pos / (double)buffer_second_size();
1239 duration = ip_duration(ip);
1240 if (duration < 0) {
1241 /* can't seek */
1242 d_print("can't seek\n");
1243 player_unlock();
1244 return;
1245 }
1246 if (relative) {
1247 new_pos = pos + offset;
1248 if (new_pos < 0.0)
1249 new_pos = 0.0;
1250 if (offset > 0.0) {
1251 /* seeking forward */
1252 if (new_pos > duration) {
1253 player_unlock();
1254 cmus_next();
1255 return;
1256 }
1257 if (new_pos < 0.0)
1258 new_pos = 0.0;
1259 if (new_pos < pos - 0.5) {
1260 /* must seek at least 0.5s */
1261 d_print("must seek at least 0.5s\n");
1262 player_unlock();
1263 return;
1264 }
1265 }
1266 } else {
1267 new_pos = offset;
1268 if (new_pos < 0.0) {
1269 d_print("seek offset negative\n");
1270 player_unlock();
1271 return;
1272 }
1273 if (new_pos > duration - 5.0) {
1274 new_pos = duration - 5.0;
1275 if (new_pos < 0.0)
1276 new_pos = 0.0;
1277 }
1278 }
1279 /* d_print("seeking %g/%g (%g from eof)\n", new_pos, duration, duration - new_pos); */
1280 rc = ip_seek(ip, new_pos);
1281 if (rc == 0) {
1282 d_print("doing op_drop after seek\n");
1283 op_drop();
1284 reset_buffer();
1285 consumer_pos = new_pos * buffer_second_size();
1286 scale_pos = consumer_pos;
1287 _consumer_position_update();
1288 if (stopped && !start_playing) {
1289 _producer_pause();
1290 _consumer_pause();
1291 _player_status_changed();
1292 }
1293 } else {
1294 player_ip_error(rc, "seeking in file %s", ip_get_filename(ip));
1295 d_print("error: ip_seek returned %d\n", rc);
1296 }
1297 }
1298 mpris_seeked();
1299 player_unlock();
1300 }
1301
1302 /*
1303 * change output plugin without stopping playback
1304 */
player_set_op(const char * name)1305 void player_set_op(const char *name)
1306 {
1307 int rc;
1308
1309 player_lock();
1310
1311 /* drop needed because close drains the buffer */
1312 if (consumer_status == CS_PAUSED)
1313 op_drop();
1314
1315 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED)
1316 op_close();
1317
1318 if (name) {
1319 d_print("setting op to '%s'\n", name);
1320 rc = op_select(name);
1321 } else {
1322 /* first initialized plugin */
1323 d_print("selecting first initialized op\n");
1324 rc = op_select_any();
1325 }
1326 if (rc) {
1327 _consumer_status_update(CS_STOPPED);
1328
1329 _producer_stop();
1330 if (name)
1331 player_op_error(rc, "selecting output plugin '%s'", name);
1332 else
1333 player_op_error(rc, "selecting any output plugin");
1334 player_unlock();
1335 return;
1336 }
1337
1338 if (consumer_status == CS_PLAYING || consumer_status == CS_PAUSED) {
1339 set_buffer_sf();
1340 rc = op_open(buffer_sf, buffer_channel_map);
1341 if (rc) {
1342 _consumer_status_update(CS_STOPPED);
1343 _producer_stop();
1344 player_op_error(rc, "opening audio device");
1345 player_unlock();
1346 return;
1347 }
1348 if (consumer_status == CS_PAUSED)
1349 op_pause();
1350 }
1351
1352 player_unlock();
1353 }
1354
player_set_buffer_chunks(unsigned int nr_chunks)1355 void player_set_buffer_chunks(unsigned int nr_chunks)
1356 {
1357 player_lock();
1358 _producer_stop();
1359 _consumer_stop();
1360
1361 buffer_nr_chunks = nr_chunks;
1362 buffer_init();
1363
1364 _player_status_changed();
1365 player_unlock();
1366 }
1367
player_get_buffer_chunks(void)1368 int player_get_buffer_chunks(void)
1369 {
1370 return buffer_nr_chunks;
1371 }
1372
player_set_soft_volume(int l,int r)1373 void player_set_soft_volume(int l, int r)
1374 {
1375 consumer_lock();
1376 soft_vol_l = l;
1377 soft_vol_r = r;
1378 consumer_unlock();
1379 }
1380
player_set_soft_vol(int soft)1381 void player_set_soft_vol(int soft)
1382 {
1383 consumer_lock();
1384 /* don't mess with scale_pos if soft_vol or replaygain is already enabled */
1385 if (!soft_vol && !replaygain)
1386 scale_pos = consumer_pos;
1387 soft_vol = soft;
1388 consumer_unlock();
1389 }
1390
calc_vol(int val,int old,int max_vol,unsigned int flags)1391 static int calc_vol(int val, int old, int max_vol, unsigned int flags)
1392 {
1393 if (flags & VF_RELATIVE) {
1394 if (flags & VF_PERCENTAGE)
1395 val = scale_from_percentage(val, max_vol);
1396 val += old;
1397 } else if (flags & VF_PERCENTAGE) {
1398 val = scale_from_percentage(val, max_vol);
1399 }
1400 return clamp(val, 0, max_vol);
1401 }
1402
player_set_vol(int l,int lf,int r,int rf)1403 int player_set_vol(int l, int lf, int r, int rf)
1404 {
1405 int rc = OP_ERROR_SUCCESS;
1406 if (soft_vol) {
1407 l = calc_vol(l, soft_vol_l, 100, lf);
1408 r = calc_vol(r, soft_vol_r, 100, rf);
1409 player_set_soft_volume(l, r);
1410 } else {
1411 mixer_read_volume();
1412 l = calc_vol(l, volume_l, volume_max, lf);
1413 r = calc_vol(r, volume_r, volume_max, rf);
1414 rc = mixer_set_volume(l, r);
1415 mixer_read_volume();
1416 }
1417 return rc;
1418 }
1419
player_set_rg(enum replaygain rg)1420 void player_set_rg(enum replaygain rg)
1421 {
1422 player_lock();
1423 /* don't mess with scale_pos if soft_vol or replaygain is already enabled */
1424 if (!soft_vol && !replaygain)
1425 scale_pos = consumer_pos;
1426 replaygain = rg;
1427
1428 player_info_priv_lock();
1429 update_rg_scale();
1430 player_info_priv_unlock();
1431
1432 player_unlock();
1433 }
1434
player_set_rg_limit(int limit)1435 void player_set_rg_limit(int limit)
1436 {
1437 player_lock();
1438 replaygain_limit = limit;
1439
1440 player_info_priv_lock();
1441 update_rg_scale();
1442 player_info_priv_unlock();
1443
1444 player_unlock();
1445 }
1446
player_set_rg_preamp(double db)1447 void player_set_rg_preamp(double db)
1448 {
1449 player_lock();
1450 replaygain_preamp = db;
1451
1452 player_info_priv_lock();
1453 update_rg_scale();
1454 player_info_priv_unlock();
1455
1456 player_unlock();
1457 }
1458
player_info_snapshot(void)1459 void player_info_snapshot(void)
1460 {
1461 player_info_priv_lock();
1462
1463 free(player_info.error_msg);
1464 if (player_info.ti)
1465 track_info_unref(player_info.ti);
1466 memcpy(&player_info, &player_info_priv, sizeof(player_info));
1467 if (player_info.ti)
1468 track_info_ref(player_info.ti);
1469
1470 player_info_priv.file_changed = 0;
1471 player_info_priv.metadata_changed = 0;
1472 player_info_priv.status_changed = 0;
1473 player_info_priv.position_changed = 0;
1474 player_info_priv.buffer_fill_changed = 0;
1475 player_info_priv.error_msg = NULL;
1476
1477 player_info_priv_unlock();
1478 }
1479
player_metadata_lock(void)1480 void player_metadata_lock(void)
1481 {
1482 cmus_mutex_lock(&player_info_mutex);
1483 }
1484
player_metadata_unlock(void)1485 void player_metadata_unlock(void)
1486 {
1487 cmus_mutex_unlock(&player_info_mutex);
1488 }
1489