2 * Copyright 2004-2006 Timo Hirvonen
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37 enum producer_status
{
44 enum consumer_status
{
50 struct player_info player_info
= {
51 .mutex
= CMUS_MUTEX_INITIALIZER
,
54 .status
= PLAYER_STATUS_STOPPED
,
62 .metadata_changed
= 0,
64 .position_changed
= 0,
65 .buffer_fill_changed
= 0,
69 /* continue playing after track is finished? */
72 static const struct player_callbacks
*player_cbs
= NULL
;
74 static sample_format_t buffer_sf
;
76 static pthread_t producer_thread
;
77 static pthread_mutex_t producer_mutex
= CMUS_MUTEX_INITIALIZER
;
78 static int producer_running
= 1;
79 static enum producer_status producer_status
= PS_UNLOADED
;
80 static struct input_plugin
*ip
= NULL
;
82 static pthread_t consumer_thread
;
83 static pthread_mutex_t consumer_mutex
= CMUS_MUTEX_INITIALIZER
;
84 static int consumer_running
= 1;
85 static enum consumer_status consumer_status
= CS_STOPPED
;
86 static int consumer_pos
= 0;
88 /* usually same as consumer_pos, sometimes less than consumer_pos */
89 static int soft_vol_pos
;
93 #define producer_lock() cmus_mutex_lock(&producer_mutex)
94 #define producer_unlock() cmus_mutex_unlock(&producer_mutex)
96 #define consumer_lock() cmus_mutex_lock(&consumer_mutex)
97 #define consumer_unlock() cmus_mutex_unlock(&consumer_mutex)
99 #define player_lock() \
105 #define player_unlock() \
113 static void reset_buffer(void)
120 static void set_buffer_sf(sample_format_t sf
)
124 /* ip_read converts samples to this format */
125 if (sf_get_channels(buffer_sf
) <= 2 && sf_get_bits(buffer_sf
) <= 16) {
126 buffer_sf
&= SF_RATE_MASK
;
127 buffer_sf
|= sf_channels(2) | sf_bits(16) | sf_signed(1);
131 #define SOFT_VOL_SCALE 65536
133 /* coefficients for volumes 0..99, for 100 65536 is used
134 * data copied from alsa-lib src/pcm/pcm_softvol.c
136 static const unsigned short soft_vol_db
[100] = {
137 0x0000, 0x0110, 0x011c, 0x012f, 0x013d, 0x0152, 0x0161, 0x0179,
138 0x018a, 0x01a5, 0x01c1, 0x01d5, 0x01f5, 0x020b, 0x022e, 0x0247,
139 0x026e, 0x028a, 0x02b6, 0x02d5, 0x0306, 0x033a, 0x035f, 0x0399,
140 0x03c2, 0x0403, 0x0431, 0x0479, 0x04ac, 0x04fd, 0x0553, 0x058f,
141 0x05ef, 0x0633, 0x069e, 0x06ea, 0x0761, 0x07b5, 0x083a, 0x0898,
142 0x092c, 0x09cb, 0x0a3a, 0x0aeb, 0x0b67, 0x0c2c, 0x0cb6, 0x0d92,
143 0x0e2d, 0x0f21, 0x1027, 0x10de, 0x1202, 0x12cf, 0x1414, 0x14f8,
144 0x1662, 0x1761, 0x18f5, 0x1a11, 0x1bd3, 0x1db4, 0x1f06, 0x211d,
145 0x2297, 0x24ec, 0x2690, 0x292a, 0x2aff, 0x2de5, 0x30fe, 0x332b,
146 0x369f, 0x390d, 0x3ce6, 0x3f9b, 0x43e6, 0x46eb, 0x4bb3, 0x4f11,
147 0x5466, 0x5a18, 0x5e19, 0x6472, 0x68ea, 0x6ffd, 0x74f8, 0x7cdc,
148 0x826a, 0x8b35, 0x9499, 0x9b35, 0xa5ad, 0xad0b, 0xb8b7, 0xc0ee,
149 0xcdf1, 0xd71a, 0xe59c, 0xefd3
152 static inline void scale_sample(signed short *buf
, int i
, int vol
)
157 buf
[i
] = (sample
* vol
- SOFT_VOL_SCALE
/ 2) / SOFT_VOL_SCALE
;
159 buf
[i
] = (sample
* vol
+ SOFT_VOL_SCALE
/ 2) / SOFT_VOL_SCALE
;
163 static void soft_vol_scale(char *buffer
, int *countp
)
167 int ch
, bits
, l
, r
, i
;
169 if (consumer_pos
!= soft_vol_pos
) {
170 int offs
= soft_vol_pos
- consumer_pos
;
178 soft_vol_pos
+= count
;
179 buf
= (signed short *)buffer
;
181 if (soft_vol_l
== 100 && soft_vol_r
== 100)
184 ch
= sf_get_channels(buffer_sf
);
185 bits
= sf_get_bits(buffer_sf
);
186 if (ch
!= 2 || bits
!= 16)
191 if (soft_vol_l
!= 100)
192 l
= soft_vol_db
[soft_vol_l
];
193 if (soft_vol_r
!= 100)
194 r
= soft_vol_db
[soft_vol_r
];
196 for (i
= 0; i
< count
/ 4; i
++) {
197 scale_sample(buf
, i
* 2, l
);
198 scale_sample(buf
, i
* 2 + 1, r
);
202 static inline int buffer_second_size(void)
204 return sf_get_second_size(buffer_sf
);
207 static inline int get_next(char **filename
)
209 return player_cbs
->get_next(filename
);
212 /* updating player status {{{ */
214 static inline void file_changed(void)
217 if (producer_status
== PS_UNLOADED
) {
218 player_info
.filename
[0] = 0;
220 strncpy(player_info
.filename
, ip_get_filename(ip
), sizeof(player_info
.filename
));
221 player_info
.filename
[sizeof(player_info
.filename
) - 1] = 0;
223 d_print("%s\n", player_info
.filename
);
224 player_info
.metadata
[0] = 0;
225 player_info
.file_changed
= 1;
226 player_info_unlock();
229 static inline void metadata_changed(void)
232 d_print("metadata changed: %s\n", ip_get_metadata(ip
));
233 memcpy(player_info
.metadata
, ip_get_metadata(ip
), 255 * 16 + 1);
234 player_info
.metadata_changed
= 1;
235 player_info_unlock();
238 static inline void volume_update(int left
, int right
)
240 if (player_info
.vol_left
== left
&& player_info
.vol_right
== right
)
244 player_info
.vol_left
= left
;
245 player_info
.vol_right
= right
;
246 player_info
.vol_changed
= 1;
247 player_info_unlock();
250 static void player_error(const char *msg
)
253 player_info
.status
= consumer_status
;
255 player_info
.buffer_fill
= buffer_get_filled_chunks();
256 player_info
.buffer_size
= buffer_nr_chunks
;
257 player_info
.status_changed
= 1;
259 free(player_info
.error_msg
);
260 player_info
.error_msg
= xstrdup(msg
);
261 player_info_unlock();
263 d_print("ERROR: '%s'\n", msg
);
266 static void __FORMAT(2, 3) player_ip_error(int rc
, const char *format
, ...)
273 va_start(ap
, format
);
274 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
278 msg
= ip_get_error_msg(ip
, rc
, buffer
);
283 static void __FORMAT(2, 3) player_op_error(int rc
, const char *format
, ...)
290 va_start(ap
, format
);
291 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
295 msg
= op_get_error_msg(rc
, buffer
);
300 /* FIXME: don't poll */
301 static void mixer_check(void)
303 static struct timeval old_t
= { 0L, 0L };
308 gettimeofday(&t
, NULL
);
309 usec
= t
.tv_usec
- old_t
.tv_usec
;
310 sec
= t
.tv_sec
- old_t
.tv_sec
;
312 /* multiplying sec with 1e6 can overflow */
319 if (!op_get_volume(&l
, &r
))
324 * buffer-fill changed
326 static void __producer_buffer_fill_update(void)
331 fill
= buffer_get_filled_chunks();
332 if (fill
!= player_info
.buffer_fill
) {
334 player_info
.buffer_fill
= fill
;
335 player_info
.buffer_fill_changed
= 1;
337 player_info_unlock();
341 * playing position changed
343 static void __consumer_position_update(void)
345 static int old_pos
= -1;
349 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
)
350 pos
= consumer_pos
/ buffer_second_size();
351 if (pos
!= old_pos
) {
356 player_info
.pos
= pos
;
357 player_info
.position_changed
= 1;
358 player_info_unlock();
363 * something big happened (stopped/paused/unpaused...)
365 static void __player_status_changed(void)
370 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
)
371 pos
= consumer_pos
/ buffer_second_size();
374 player_info
.status
= consumer_status
;
375 player_info
.pos
= pos
;
376 player_info
.buffer_fill
= buffer_get_filled_chunks();
377 player_info
.buffer_size
= buffer_nr_chunks
;
378 player_info
.status_changed
= 1;
379 player_info_unlock();
382 /* updating player status }}} */
384 static void __prebuffer(void)
388 BUG_ON(producer_status
!= PS_PLAYING
);
389 if (ip_is_remote(ip
)) {
390 limit_chunks
= buffer_nr_chunks
;
392 int limit_ms
, limit_size
;
395 limit_size
= limit_ms
* buffer_second_size() / 1000;
396 limit_chunks
= limit_size
/ CHUNK_SIZE
;
397 if (limit_chunks
< 1)
401 int nr_read
, size
, filled
;
404 filled
= buffer_get_filled_chunks();
405 /* d_print("PREBUF: %2d / %2d\n", filled, limit_chunks); */
408 //BUG_ON(filled > limit_chunks);
410 if (filled
>= limit_chunks
)
413 size
= buffer_get_wpos(&wpos
);
414 nr_read
= ip_read(ip
, wpos
, size
);
416 if (nr_read
== -1 && errno
== EAGAIN
)
418 player_ip_error(nr_read
, "reading file %s", ip_get_filename(ip
));
420 producer_status
= PS_UNLOADED
;
423 if (ip_metadata_changed(ip
))
426 /* buffer_fill with 0 count marks current chunk filled */
427 buffer_fill(nr_read
);
429 __producer_buffer_fill_update();
437 /* setting producer status {{{ */
439 static void __producer_play(void)
441 if (producer_status
== PS_UNLOADED
) {
444 if (get_next(&filename
) == 0) {
447 ip
= ip_new(filename
);
450 player_ip_error(rc
, "opening file `%s'", filename
);
454 producer_status
= PS_PLAYING
;
459 } else if (producer_status
== PS_PLAYING
) {
460 if (ip_seek(ip
, 0.0) == 0) {
463 } else if (producer_status
== PS_STOPPED
) {
468 player_ip_error(rc
, "opening file `%s'", ip_get_filename(ip
));
470 producer_status
= PS_UNLOADED
;
473 producer_status
= PS_PLAYING
;
475 } else if (producer_status
== PS_PAUSED
) {
476 producer_status
= PS_PLAYING
;
480 static void __producer_stop(void)
482 if (producer_status
== PS_PLAYING
|| producer_status
== PS_PAUSED
) {
484 producer_status
= PS_STOPPED
;
489 static void __producer_unload(void)
492 if (producer_status
== PS_STOPPED
) {
494 producer_status
= PS_UNLOADED
;
498 static void __producer_pause(void)
500 if (producer_status
== PS_PLAYING
) {
501 producer_status
= PS_PAUSED
;
502 } else if (producer_status
== PS_PAUSED
) {
503 producer_status
= PS_PLAYING
;
507 static void __producer_set_file(const char *filename
)
510 ip
= ip_new(filename
);
511 producer_status
= PS_STOPPED
;
515 /* setting producer status }}} */
517 /* setting consumer status {{{ */
519 static void __consumer_play(void)
521 if (consumer_status
== CS_PLAYING
) {
523 } else if (consumer_status
== CS_STOPPED
) {
526 set_buffer_sf(ip_get_sf(ip
));
527 rc
= op_open(buffer_sf
);
529 player_op_error(rc
, "opening audio device");
531 consumer_status
= CS_PLAYING
;
533 } else if (consumer_status
== CS_PAUSED
) {
535 consumer_status
= CS_PLAYING
;
539 static void __consumer_drain_and_stop(void)
541 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
) {
543 consumer_status
= CS_STOPPED
;
547 static void __consumer_stop(void)
549 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
) {
552 consumer_status
= CS_STOPPED
;
556 static void __consumer_pause(void)
558 if (consumer_status
== CS_PLAYING
) {
560 consumer_status
= CS_PAUSED
;
561 } else if (consumer_status
== CS_PAUSED
) {
563 consumer_status
= CS_PLAYING
;
567 /* setting consumer status }}} */
569 static int change_sf(sample_format_t sf
, int drop
)
571 int old_sf
= buffer_sf
;
574 if (buffer_sf
!= old_sf
) {
581 rc
= op_open(buffer_sf
);
583 player_op_error(rc
, "opening audio device");
584 consumer_status
= CS_STOPPED
;
588 } else if (consumer_status
== CS_PAUSED
) {
592 consumer_status
= CS_PLAYING
;
596 static void __consumer_handle_eof(void)
600 if (ip_is_remote(ip
)) {
602 __consumer_drain_and_stop();
603 player_error("lost connection");
607 if (get_next(&filename
) == 0) {
609 ip
= ip_new(filename
);
610 producer_status
= PS_STOPPED
;
611 /* PS_STOPPED, CS_PLAYING */
614 if (producer_status
== PS_UNLOADED
) {
620 if (!change_sf(ip_get_sf(ip
), 0))
624 __consumer_drain_and_stop();
630 __consumer_drain_and_stop();
633 __player_status_changed();
636 static void *consumer_loop(void *arg
)
644 if (!consumer_running
)
647 if (consumer_status
== CS_PAUSED
|| consumer_status
== CS_STOPPED
) {
653 space
= op_buffer_space();
656 __consumer_position_update();
661 /* d_print("BS: %6d %3d\n", space, space * 1000 / (44100 * 2 * 2)); */
664 /* 25 ms is 4410 B */
666 __consumer_position_update();
672 size
= buffer_get_rpos(&rpos
);
675 if (producer_status
!= PS_PLAYING
) {
680 /* must recheck rpos */
681 size
= buffer_get_rpos(&rpos
);
683 /* OK. now it's safe to check if we are at EOF */
686 __consumer_handle_eof();
691 /* possible underrun */
693 __consumer_position_update();
695 /* d_print("possible underrun\n"); */
701 /* player_buffer and ip.eof were inconsistent */
707 soft_vol_scale(rpos
, &size
);
708 rc
= op_write(rpos
, size
);
710 d_print("op_write returned %d %s\n", rc
,
711 rc
== -1 ? strerror(errno
) : "");
715 consumer_status
= CS_STOPPED
;
731 static void *producer_loop(void *arg
)
734 /* number of chunks to fill
735 * too big => seeking is slow
736 * too small => underruns?
738 const int chunks
= 1;
739 int size
, nr_read
, i
;
743 if (!producer_running
)
746 if (producer_status
== PS_UNLOADED
||
747 producer_status
== PS_PAUSED
||
748 producer_status
== PS_STOPPED
|| ip_eof(ip
)) {
754 size
= buffer_get_wpos(&wpos
);
761 nr_read
= ip_read(ip
, wpos
, size
);
763 if (nr_read
!= -1 || errno
!= EAGAIN
) {
764 player_ip_error(nr_read
, "reading file %s",
765 ip_get_filename(ip
));
767 producer_status
= PS_UNLOADED
;
773 if (ip_metadata_changed(ip
))
776 /* buffer_fill with 0 count marks current chunk filled */
777 buffer_fill(nr_read
);
779 /* consumer handles EOF */
790 __producer_buffer_fill_update();
797 void player_load_plugins(void)
803 void player_init(const struct player_callbacks
*callbacks
)
806 #if defined(__linux__) || defined(__FreeBSD__)
809 pthread_attr_t
*attrp
= NULL
;
811 /* 1 s is 176400 B (0.168 MB)
814 buffer_nr_chunks
= 10 * 44100 * 16 / 8 * 2 / CHUNK_SIZE
;
817 player_cbs
= callbacks
;
819 #if defined(__linux__) || defined(__FreeBSD__)
820 rc
= pthread_attr_init(&attr
);
822 rc
= pthread_attr_setschedpolicy(&attr
, SCHED_RR
);
824 d_print("could not set real-time scheduling priority: %s\n", strerror(rc
));
826 struct sched_param param
;
828 d_print("using real-time scheduling\n");
829 param
.sched_priority
= sched_get_priority_max(SCHED_RR
);
830 d_print("setting priority to %d\n", param
.sched_priority
);
831 rc
= pthread_attr_setschedparam(&attr
, ¶m
);
837 rc
= pthread_create(&producer_thread
, NULL
, producer_loop
, NULL
);
840 rc
= pthread_create(&consumer_thread
, attrp
, consumer_loop
, NULL
);
842 d_print("could not create thread using real-time scheduling: %s\n", strerror(rc
));
843 rc
= pthread_create(&consumer_thread
, NULL
, consumer_loop
, NULL
);
847 /* update player_info.cont etc. */
849 __player_status_changed();
853 void player_exit(void)
858 consumer_running
= 0;
859 producer_running
= 0;
862 rc
= pthread_join(consumer_thread
, NULL
);
864 rc
= pthread_join(producer_thread
, NULL
);
870 void player_stop(void)
875 __player_status_changed();
879 void player_play(void)
884 if (producer_status
== PS_PLAYING
&& ip_is_remote(ip
)) {
885 /* seeking not allowed */
889 prebuffer
= consumer_status
== CS_STOPPED
;
891 if (producer_status
== PS_PLAYING
) {
893 if (consumer_status
!= CS_PLAYING
)
898 __player_status_changed();
899 if (consumer_status
== CS_PLAYING
&& prebuffer
)
904 void player_pause(void)
907 if (ip
&& ip_is_remote(ip
)) {
908 /* pausing not allowed */
914 __player_status_changed();
918 void player_set_file(const char *filename
)
921 __producer_set_file(filename
);
922 if (producer_status
== PS_UNLOADED
) {
928 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
) {
930 if (producer_status
== PS_UNLOADED
) {
934 change_sf(ip_get_sf(ip
), 1);
937 __player_status_changed();
938 if (producer_status
== PS_PLAYING
)
943 void player_play_file(const char *filename
)
946 __producer_set_file(filename
);
947 if (producer_status
== PS_UNLOADED
) {
955 /* PS_UNLOADED,PS_PLAYING */
956 if (producer_status
== PS_UNLOADED
) {
962 if (consumer_status
== CS_STOPPED
) {
964 if (consumer_status
== CS_STOPPED
)
967 change_sf(ip_get_sf(ip
), 1);
970 __player_status_changed();
971 if (producer_status
== PS_PLAYING
)
976 void player_seek(double offset
, int relative
)
979 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
) {
980 double pos
, duration
, new_pos
;
983 pos
= (double)consumer_pos
/ (double)buffer_second_size();
984 duration
= ip_duration(ip
);
987 d_print("can't seek\n");
992 new_pos
= pos
+ offset
;
996 /* seeking forward */
997 if (new_pos
> duration
- 5.0)
998 new_pos
= duration
- 5.0;
1001 if (new_pos
< pos
- 0.5) {
1002 /* must seek at least 0.5s */
1003 d_print("must seek at least 0.5s\n");
1010 if (new_pos
< 0.0) {
1011 d_print("seek offset negative\n");
1015 if (new_pos
> duration
) {
1016 d_print("seek offset too large\n");
1021 /* d_print("seeking %g/%g (%g from eof)\n", new_pos, duration, duration - new_pos); */
1022 rc
= ip_seek(ip
, new_pos
);
1024 /* d_print("doing op_drop after seek\n"); */
1027 consumer_pos
= new_pos
* buffer_second_size();
1028 soft_vol_pos
= consumer_pos
;
1029 __consumer_position_update();
1031 d_print("error: ip_seek returned %d\n", rc
);
1038 * change output plugin without stopping playback
1040 void player_set_op(const char *name
)
1046 /* drop needed because close drains the buffer */
1047 if (consumer_status
== CS_PAUSED
)
1050 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
)
1054 d_print("setting op to '%s'\n", name
);
1055 rc
= op_select(name
);
1057 /* first initialized plugin */
1058 d_print("selecting first initialized op\n");
1059 rc
= op_select_any();
1062 consumer_status
= CS_STOPPED
;
1065 player_op_error(rc
, "selecting output plugin '%s'", name
);
1070 if (consumer_status
== CS_PLAYING
|| consumer_status
== CS_PAUSED
) {
1071 set_buffer_sf(ip_get_sf(ip
));
1072 rc
= op_open(buffer_sf
);
1074 consumer_status
= CS_STOPPED
;
1076 player_op_error(rc
, "opening audio device");
1080 if (consumer_status
== CS_PAUSED
)
1084 if (!op_get_volume(&l
, &r
))
1085 volume_update(l
, r
);
1090 char *player_get_op(void)
1092 return op_get_current();
1095 void player_set_buffer_chunks(unsigned int nr_chunks
)
1106 buffer_nr_chunks
= nr_chunks
;
1109 __player_status_changed();
1113 int player_get_buffer_chunks(void)
1115 return buffer_nr_chunks
;
1118 int player_get_fileinfo(const char *filename
, int *duration
,
1119 struct keyval
**comments
)
1121 struct input_plugin
*plug
;
1126 plug
= ip_new(filename
);
1127 if (ip_is_remote(plug
)) {
1128 *comments
= xnew0(struct keyval
, 1);
1139 rc
= -PLAYER_ERROR_NOT_SUPPORTED
;
1142 *duration
= ip_duration(plug
);
1143 rc
= ip_read_comments(plug
, comments
);
1148 int player_get_volume(int *left
, int *right
)
1153 rc
= op_get_volume(left
, right
);
1158 int player_set_volume(int left
, int right
)
1163 rc
= op_set_volume(left
, right
);
1165 volume_update(left
, right
);
1170 void player_set_soft_vol(int soft
)
1175 /* don't mess with soft_vol_pos if soft_vol is already true */
1177 soft_vol_pos
= consumer_pos
;
1178 op_set_soft_vol(soft
);
1179 if (!op_get_volume(&l
, &r
))
1180 volume_update(l
, r
);
1184 int player_set_op_option(unsigned int id
, const char *val
)
1191 rc
= op_set_option(id
, val
);
1192 __player_status_changed();
1197 int player_get_op_option(unsigned int id
, char **val
)
1202 rc
= op_get_option(id
, val
);
1207 int player_for_each_op_option(void (*callback
)(unsigned int id
, const char *key
))
1212 op_for_each_option(callback
);
1213 __player_status_changed();
1218 void player_dump_plugins(void)