Codebase list squeezelite / b3a18df
New upstream version 1.8 tony mancill 3 years ago
36 changed file(s) with 11230 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Version 1.0 - 15/2/13
1 =====================
2 - initial release
3
4 Version 1.1 - 12/4/13
5 =====================
6
7 Minor changes
8 - add timeout on slimproto connection to detect dead server
9 - fix issue with clipping on windows by disabling portaudio dither
10 - silence alsa error messages on linux alsa builds unless debugging is enabled
11 - hide some additional error messages unless debuging is enabled so usb dacs produce less error messages when turned off and on
12
13 Version 1.2 - 6/7/13
14 ====================
15
16 Features
17 - support of upsampling via libsoxr
18
19 Minor changes
20 - command line option for setting the service address now requires "-s" before the server address
21 - fixes a bug where the channels could become swapped when using S16_LE ALSA output
22 - falls back to polling for a new server if one is not found for more than 30 seconds
23 - fixes play of wav/aiff local files when the LocalPlayer plugin is active
24
25 Version 1.3 - 6/10/13
26 =====================
27
28 Features
29 - support for wma/alac decode via ffmpeg library (requires compilation with -DFFMPEG)
30 - support for export of audio data to jivelite to enable visulizations on linux (requires compilation with -DVISEXPORT)
31
32 Minor changes
33 - support async as well as sync resampling rates
34 - support on/off of audio device with portaudio
35 - improved gapless support for aac/mad when skipping to mid track (based on patches from Wouter Ellenbroek)
36 - various bug fixes
37
38 Version 1.3.1 - 25/11/13
39 ========================
40
41 Minor changes
42 - support of compile time linking for distro packaging, uses -DLINKALL option
43
44 Version 1.4 28/12/13
45 ====================
46
47 Features
48 - native support of dsd playback to dop capable dac or via conversion to pcm and resampling
49 - support dop in flac playback to dop dacs
50 - support of output to stdout
51
52 Minor changes
53 - support of resampling only when sample rate is not natively supported
54 - fix problem with libmpg123 playback not playing to end of track
55 - add ablity for player name change to be stored locally in a file (to emulate hardware where name is stored on player)
56
57 Version 1.5 12/1/14
58 ===================
59
60 Minor changes
61 - add configurable delay for switch between pcm and dop
62 - allow visexport to work with jivelite running as any user
63 - bug fixes for dsf playback, for status progress on windows using wdm-ks output, and to avoid 100% cpu
64 - change some logging levels for slimproto to aid readability
65
66 Version 1.6 23/3/14
67 ===================
68
69 Minor changes
70 - add support for direct file playback on windows
71 - add configurable delay for switch between pcm sample rates
72 - support build on freebsd
73 - fix gapless playback on portaudio builds
74 - fix gapless playback for mp3 localfile case with tags at start of file
75
76 Version 1.6.1 22/4/14
77 =====================
78
79 Minor changes
80 - fix bug with PA version changing sample rate between tracks
81 - fix crash when skipping in ogg while resampling
82 - fix typo
83
84 Version 1.6.2 26/5/14
85 =====================
86
87 Minor changes
88 - fix XRUN on track change when resampling on low power cpus
89 - log command line to logfile when debugging enabled
90 - option to exclude codecs (-e)
91 - support parallel execution of libsoxr
92
93 Version 1.6.3 14/6/14
94 =====================
95
96 Minor changes
97 - reduce time to start track when playing local files
98 - disable use of OPENMP when RESAMPLE build option defined, add new option RESAMPLE_MP to enable it
99
100 Version 1.6.4 7/7/14
101 ====================
102
103 Minor changes
104 - improve synchronisation feedback accuracy
105
106 Version 1.6.5 21/11/14
107 ======================
108
109 Minor changes
110 - fix problem opening ALSA device if 44100 is not supported
111 - trap setting of hw player mac address
112
113 Version 1.7 1/1/15
114 ==================
115
116 Minor changes
117 - allow player modelname to be set at compile or run time
118 - workaround alsa drivers reporting very large number of available frames
119 - fix clicks on localfile playback of AIFF files
120 - add -P option to store process id in a file
121 - improve error messages for command line parsing
122
123 Version 1.7.1 10/1/15
124 =====================
125
126 Minor changes
127 - fix crash which could occur when resampling
128
129 Version 1.8 1/2/15
130 ==================
131
132 Features
133 - support for closing output device when idle with -C option
134 - support for basic IR input using LIRC on Linux
135 - support for volume adjustment or unmuting of alsa mixer
136 - support for inverting output polarity via LMS setting (requires recent 7.9 server)
0 Squeezelite - lightweight headless squeezebox emulator
1
2 (c) Adrian Smith 2012-2015, triode1@btinternet.com
3
4 Released under GPLv3 license:
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19
20 ---------------------------------------------------------------------
21
22 If built with DSD support, this software also includes code subject to the following license:
23
24 Copyright 2009, 2011 Sebastian Gesemann. All rights reserved.
25
26 Redistribution and use in source and binary forms, with or without modification, are
27 permitted provided that the following conditions are met:
28
29 1. Redistributions of source code must retain the above copyright notice, this list of
30 conditions and the following disclaimer.
31
32 2. Redistributions in binary form must reproduce the above copyright notice, this list
33 of conditions and the following disclaimer in the documentation and/or other materials
34 provided with the distribution.
35
36 THIS SOFTWARE IS PROVIDED BY SEBASTIAN GESEMANN ''AS IS'' AND ANY EXPRESS OR IMPLIED
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
38 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEBASTIAN GESEMANN OR
39 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
42 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
44 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
46 The views and conclusions contained in the software and documentation are those of the
47 authors and should not be interpreted as representing official policies, either expressed
48 or implied, of Sebastian Gesemann.
0 # Cross compile support - create a Makefile which defines these three variables and then includes this Makefile...
1 CFLAGS ?= -Wall -fPIC -O2 $(OPTS)
2 LDFLAGS ?= -lasound -lpthread -lm -lrt
3 EXECUTABLE ?= squeezelite
4
5 # passing one or more of these in $(OPTS) enables optional feature inclusion
6 OPT_DSD = -DDSD
7 OPT_FF = -DFFMPEG
8 OPT_LINKALL = -DLINKALL
9 OPT_RESAMPLE= -DRESAMPLE
10 OPT_VIS = -DVISEXPORT
11 OPT_IR = -DIR
12
13 SOURCES = \
14 main.c slimproto.c buffer.c stream.c utils.c \
15 output.c output_alsa.c output_pa.c output_stdout.c output_pack.c decode.c \
16 flac.c pcm.c mad.c vorbis.c faad.c mpg.c
17
18 SOURCES_DSD = dsd.c dop.c dsd2pcm/dsd2pcm.c
19 SOURCES_FF = ffmpeg.c
20 SOURCES_RESAMPLE = process.c resample.c
21 SOURCES_VIS = output_vis.c
22 SOURCES_IR = ir.c
23
24 LINK_LINUX = -ldl
25
26 LINKALL = -lFLAC -lmad -lvorbisfile -lfaad -lmpg123
27 LINKALL_FF = -lavcodec -lavformat -lavutil
28 LINKALL_RESAMPLE = -lsoxr
29 LINKALL_IR = -llirc_client
30
31 DEPS = squeezelite.h slimproto.h
32
33 UNAME = $(shell uname -s)
34
35 # add optional sources
36 ifneq (,$(findstring $(OPT_DSD), $(CFLAGS)))
37 SOURCES += $(SOURCES_DSD)
38 endif
39 ifneq (,$(findstring $(OPT_FF), $(CFLAGS)))
40 SOURCES += $(SOURCES_FF)
41 endif
42 ifneq (,$(findstring $(OPT_RESAMPLE), $(CFLAGS)))
43 SOURCES += $(SOURCES_RESAMPLE)
44 endif
45 ifneq (,$(findstring $(OPT_VIS), $(CFLAGS)))
46 SOURCES += $(SOURCES_VIS)
47 endif
48 ifneq (,$(findstring $(OPT_IR), $(CFLAGS)))
49 SOURCES += $(SOURCES_IR)
50 endif
51
52 # add optional link options
53 ifneq (,$(findstring $(OPT_LINKALL), $(CFLAGS)))
54 LDFLAGS += $(LINKALL)
55 ifneq (,$(findstring $(OPT_FF), $(CFLAGS)))
56 LDFLAGS += $(LINKALL_FF)
57 endif
58 ifneq (,$(findstring $(OPT_RESAMPLE), $(CFLAGS)))
59 LDFLAGS += $(LINKALL_RESAMPLE)
60 endif
61 ifneq (,$(findstring $(OPT_IR), $(CFLAGS)))
62 LDFLAGS += $(LINKALL_IR)
63 endif
64 else
65 # if not LINKALL and linux add LINK_LINUX
66 ifeq ($(UNAME), Linux)
67 LDFLAGS += $(LINK_LINUX)
68 endif
69 endif
70
71 OBJECTS = $(SOURCES:.c=.o)
72
73 all: $(EXECUTABLE)
74
75 $(EXECUTABLE): $(OBJECTS)
76 $(CC) $(OBJECTS) $(LDFLAGS) -o $@
77
78 $(OBJECTS): $(DEPS)
79
80 .c.o:
81 $(CC) $(CFLAGS) $(CPPFLAGS) $< -c -o $@
82
83 clean:
84 rm -f $(OBJECTS) $(EXECUTABLE)
0 CPPFLAGS = -I/usr/local/include -I/usr/local/include/portaudio2
1 LDFLAGS = -L/usr/local/lib -L/usr/local/lib/portaudio2 -lportaudio -lpthread -lm
2
3 include Makefile
0 # OSX build - adjust -I to point to header files for codecs and portaudio
1 CFLAGS = -arch x86_64 -arch i386 -Wall -fPIC -O2 -I./include $(OPTS)
2 LDFLAGS = -arch x86_64 -arch i386 -lpthread libportaudio.a -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon
3
4 EXECUTABLE ?= squeezelite-osx
5
6 include Makefile
0 # Make with portaudio rather than direct alsa
1 OPTS += -DPORTAUDIO
2 LDFLAGS = -lportaudio -lpthread -ldl -lrt
3 EXECUTABLE = squeezelite-pa
4
5 include Makefile
0 OPTS = -DRESAMPLE
1
2 include Makefile
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // fifo bufffers
21
22 #define _GNU_SOURCE
23
24 #include "squeezelite.h"
25
26 // _* called with muxtex locked
27
28 inline unsigned _buf_used(struct buffer *buf) {
29 return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->size - (buf->readp - buf->writep);
30 }
31
32 unsigned _buf_space(struct buffer *buf) {
33 return buf->size - _buf_used(buf) - 1; // reduce by one as full same as empty otherwise
34 }
35
36 unsigned _buf_cont_read(struct buffer *buf) {
37 return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->wrap - buf->readp;
38 }
39
40 unsigned _buf_cont_write(struct buffer *buf) {
41 return buf->writep >= buf->readp ? buf->wrap - buf->writep : buf->readp - buf->writep;
42 }
43
44 void _buf_inc_readp(struct buffer *buf, unsigned by) {
45 buf->readp += by;
46 if (buf->readp >= buf->wrap) {
47 buf->readp -= buf->size;
48 }
49 }
50
51 void _buf_inc_writep(struct buffer *buf, unsigned by) {
52 buf->writep += by;
53 if (buf->writep >= buf->wrap) {
54 buf->writep -= buf->size;
55 }
56 }
57
58 void buf_flush(struct buffer *buf) {
59 mutex_lock(buf->mutex);
60 buf->readp = buf->buf;
61 buf->writep = buf->buf;
62 mutex_unlock(buf->mutex);
63 }
64
65 // adjust buffer to multiple of mod bytes so reading in multiple always wraps on frame boundary
66 void buf_adjust(struct buffer *buf, size_t mod) {
67 size_t size;
68 mutex_lock(buf->mutex);
69 size = ((unsigned)(buf->base_size / mod)) * mod;
70 buf->readp = buf->buf;
71 buf->writep = buf->buf;
72 buf->wrap = buf->buf + size;
73 buf->size = size;
74 mutex_unlock(buf->mutex);
75 }
76
77 // called with mutex locked to resize, does not retain contents, reverts to original size if fails
78 void _buf_resize(struct buffer *buf, size_t size) {
79 free(buf->buf);
80 buf->buf = malloc(size);
81 if (!buf->buf) {
82 size = buf->size;
83 buf->buf= malloc(size);
84 if (!buf->buf) {
85 size = 0;
86 }
87 }
88 buf->readp = buf->buf;
89 buf->writep = buf->buf;
90 buf->wrap = buf->buf + size;
91 buf->size = size;
92 buf->base_size = size;
93 }
94
95 void buf_init(struct buffer *buf, size_t size) {
96 buf->buf = malloc(size);
97 buf->readp = buf->buf;
98 buf->writep = buf->buf;
99 buf->wrap = buf->buf + size;
100 buf->size = size;
101 buf->base_size = size;
102 mutex_create_p(buf->mutex);
103 }
104
105 void buf_destroy(struct buffer *buf) {
106 if (buf->buf) {
107 free(buf->buf);
108 buf->buf = NULL;
109 buf->size = 0;
110 buf->base_size = 0;
111 mutex_destroy(buf->mutex);
112 }
113 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // decode thread
21
22 #include "squeezelite.h"
23
24 log_level loglevel;
25
26 extern struct buffer *streambuf;
27 extern struct buffer *outputbuf;
28 extern struct streamstate stream;
29 extern struct outputstate output;
30 extern struct processstate process;
31
32 struct decodestate decode;
33 struct codec *codecs[MAX_CODECS];
34 struct codec *codec;
35 static bool running = true;
36
37 #define LOCK_S mutex_lock(streambuf->mutex)
38 #define UNLOCK_S mutex_unlock(streambuf->mutex)
39 #define LOCK_O mutex_lock(outputbuf->mutex)
40 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
41 #define LOCK_D mutex_lock(decode.mutex);
42 #define UNLOCK_D mutex_unlock(decode.mutex);
43
44 #if PROCESS
45 #define IF_DIRECT(x) if (decode.direct) { x }
46 #define IF_PROCESS(x) if (!decode.direct) { x }
47 #define MAY_PROCESS(x) { x }
48 #else
49 #define IF_DIRECT(x) { x }
50 #define IF_PROCESS(x)
51 #define MAY_PROCESS(x)
52 #endif
53
54 static void *decode_thread() {
55
56 while (running) {
57 size_t bytes, space, min_space;
58 bool toend;
59 bool ran = false;
60
61 LOCK_S;
62 bytes = _buf_used(streambuf);
63 toend = (stream.state <= DISCONNECT);
64 UNLOCK_S;
65 LOCK_O;
66 space = _buf_space(outputbuf);
67 UNLOCK_O;
68
69 LOCK_D;
70
71 if (decode.state == DECODE_RUNNING && codec) {
72
73 LOG_SDEBUG("streambuf bytes: %u outputbuf space: %u", bytes, space);
74
75 IF_DIRECT(
76 min_space = codec->min_space;
77 );
78 IF_PROCESS(
79 min_space = process.max_out_frames * BYTES_PER_FRAME;
80 );
81
82 if (space > min_space && (bytes > codec->min_read_bytes || toend)) {
83
84 decode.state = codec->decode();
85
86 IF_PROCESS(
87 if (process.in_frames) {
88 process_samples();
89 }
90
91 if (decode.state == DECODE_COMPLETE) {
92 process_drain();
93 }
94 );
95
96 if (decode.state != DECODE_RUNNING) {
97
98 LOG_INFO("decode %s", decode.state == DECODE_COMPLETE ? "complete" : "error");
99
100 LOCK_O;
101 if (output.fade_mode) _checkfade(false);
102 UNLOCK_O;
103
104 wake_controller();
105 }
106
107 ran = true;
108 }
109 }
110
111 UNLOCK_D;
112
113 if (!ran) {
114 usleep(100000);
115 }
116 }
117
118 return 0;
119 }
120
121 static thread_type thread;
122
123 void decode_init(log_level level, const char *include_codecs, const char *exclude_codecs) {
124 int i;
125
126 loglevel = level;
127
128 LOG_INFO("init decode, include codecs: %s exclude codecs: %s", include_codecs ? include_codecs : "", exclude_codecs);
129
130 // register codecs
131 // dsf,dff,alc,wma,wmap,wmal,aac,spt,ogg,ogf,flc,aif,pcm,mp3
132 i = 0;
133 #if DSD
134 if (!strstr(exclude_codecs, "dsd") && (!include_codecs || strstr(include_codecs, "dsd"))) codecs[i++] = register_dsd();
135 #endif
136 #if FFMPEG
137 if (!strstr(exclude_codecs, "alac") && (!include_codecs || strstr(include_codecs, "alac"))) codecs[i++] = register_ff("alc");
138 if (!strstr(exclude_codecs, "wma") && (!include_codecs || strstr(include_codecs, "wma"))) codecs[i++] = register_ff("wma");
139 #endif
140 if (!strstr(exclude_codecs, "aac") && (!include_codecs || strstr(include_codecs, "aac"))) codecs[i++] = register_faad();
141 if (!strstr(exclude_codecs, "ogg") && (!include_codecs || strstr(include_codecs, "ogg"))) codecs[i++] = register_vorbis();
142 if (!strstr(exclude_codecs, "flac") && (!include_codecs || strstr(include_codecs, "flac"))) codecs[i++] = register_flac();
143 if (!strstr(exclude_codecs, "pcm") && (!include_codecs || strstr(include_codecs, "pcm"))) codecs[i++] = register_pcm();
144
145 // try mad then mpg for mp3 unless command line option passed
146 if (!(strstr(exclude_codecs, "mp3") || strstr(exclude_codecs, "mad")) &&
147 (!include_codecs || strstr(include_codecs, "mp3") || strstr(include_codecs, "mad"))) codecs[i] = register_mad();
148 if (!(strstr(exclude_codecs, "mp3") || strstr(exclude_codecs, "mpg")) && !codecs[i] &&
149 (!include_codecs || strstr(include_codecs, "mp3") || strstr(include_codecs, "mpg"))) codecs[i] = register_mpg();
150
151 mutex_create(decode.mutex);
152
153 #if LINUX || OSX || FREEBSD
154 pthread_attr_t attr;
155 pthread_attr_init(&attr);
156 pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + DECODE_THREAD_STACK_SIZE);
157 pthread_create(&thread, &attr, decode_thread, NULL);
158 pthread_attr_destroy(&attr);
159 #endif
160 #if WIN
161 thread = CreateThread(NULL, DECODE_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&decode_thread, NULL, 0, NULL);
162 #endif
163
164 decode.new_stream = true;
165 decode.state = DECODE_STOPPED;
166
167 MAY_PROCESS(
168 decode.direct = true;
169 decode.process = false;
170 );
171 }
172
173 void decode_close(void) {
174 LOG_INFO("close decode");
175 LOCK_D;
176 if (codec) {
177 codec->close();
178 codec = NULL;
179 }
180 running = false;
181 UNLOCK_D;
182 #if LINUX || OSX || FREEBSD
183 pthread_join(thread, NULL);
184 #endif
185 mutex_destroy(decode.mutex);
186 }
187
188 void decode_flush(void) {
189 LOG_INFO("decode flush");
190 LOCK_D;
191 decode.state = DECODE_STOPPED;
192 IF_PROCESS(
193 process_flush();
194 );
195 UNLOCK_D;
196 }
197
198 unsigned decode_newstream(unsigned sample_rate, unsigned supported_rates[]) {
199
200 // called with O locked to get sample rate for potentially processed output stream
201 // release O mutex during process_newstream as it can take some time
202
203 MAY_PROCESS(
204 if (decode.process) {
205 UNLOCK_O;
206 sample_rate = process_newstream(&decode.direct, sample_rate, supported_rates);
207 LOCK_O;
208 }
209 );
210
211 return sample_rate;
212 }
213
214 void codec_open(u8_t format, u8_t sample_size, u8_t sample_rate, u8_t channels, u8_t endianness) {
215 int i;
216
217 LOG_INFO("codec open: '%c'", format);
218
219 LOCK_D;
220
221 decode.new_stream = true;
222 decode.state = DECODE_STOPPED;
223
224 MAY_PROCESS(
225 decode.direct = true; // potentially changed within codec when processing enabled
226 );
227
228 // find the required codec
229 for (i = 0; i < MAX_CODECS; ++i) {
230
231 if (codecs[i] && codecs[i]->id == format) {
232
233 if (codec && codec != codecs[i]) {
234 LOG_INFO("closing codec: '%c'", codec->id);
235 codec->close();
236 }
237
238 codec = codecs[i];
239
240 codec->open(sample_size, sample_rate, channels, endianness);
241
242 decode.state = DECODE_READY;
243
244 UNLOCK_D;
245 return;
246 }
247 }
248
249 UNLOCK_D;
250
251 LOG_ERROR("codec not found");
252 }
253
+102
-0
dop.c less more
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012, 2013, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // DSP over PCM (DOP) specific functions
21
22 #include "squeezelite.h"
23
24 #if DSD
25
26 extern struct buffer *outputbuf;
27 extern struct outputstate output;
28
29 #define LOCK_O mutex_lock(outputbuf->mutex)
30 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
31
32 // check for 32 dop marker frames to see if this is dop in flac
33 // dop is always encoded in 24 bit samples with marker 0x0005xxxx or 0x00FAxxxx
34 bool is_flac_dop(u32_t *lptr, u32_t *rptr, frames_t frames) {
35 int matched = 0;
36 u32_t next = 0;
37
38 while (frames--) {
39 if (((*lptr & 0x00FF0000) == 0x00050000 && (*rptr & 0x00FF0000) == 0x00050000) ||
40 ((*lptr & 0x00FF0000) == 0x00FA0000 && (*rptr & 0x00FF0000) == 0x00FA0000)) {
41 if (*lptr >> 24 == next) {
42 matched++;
43 next = ( 0x05 + 0xFA ) - next;
44 } else {
45 next = *lptr >> 24;
46 matched = 1;
47 }
48 } else {
49 return false;
50 }
51 if (matched == 32) {
52 return true;
53 }
54
55 ++lptr; ++rptr;
56 }
57 return false;
58 }
59
60 // update the dop marker and potentially invert polarity for frames in the output buffer
61 // performaned on all output including silence to maintain marker phase consitency
62 void update_dop(u32_t *ptr, frames_t frames, bool invert) {
63 static u32_t marker = 0x05;
64 if (!invert) {
65 while (frames--) {
66 u32_t scaled_marker = marker << 24;
67 *ptr = (*ptr & 0x00FFFFFF) | scaled_marker;
68 ++ptr;
69 *ptr = (*ptr & 0x00FFFFFF) | scaled_marker;
70 ++ptr;
71 marker = ( 0x05 + 0xFA ) - marker;
72 }
73 } else {
74 while (frames--) {
75 u32_t scaled_marker = marker << 24;
76 *ptr = ((~(*ptr)) & 0x00FFFFFF) | scaled_marker;
77 ++ptr;
78 *ptr = ((~(*ptr)) & 0x00FFFFFF) | scaled_marker;
79 ++ptr;
80 marker = ( 0x05 + 0xFA ) - marker;
81 }
82 }
83 }
84
85 // fill silence buffer with 10101100 which represents dop silence
86 // leave marker zero it will be updated at output, leave lsb zero
87 void dop_silence_frames(u32_t *ptr, frames_t frames) {
88 while (frames--) {
89 *ptr++ = 0x00ACAC00;
90 *ptr++ = 0x00ACAC00;
91 }
92 }
93
94 void dop_init(bool enable, unsigned delay) {
95 LOCK_O;
96 output.has_dop = enable;
97 output.dop_delay = delay;
98 UNLOCK_O;
99 }
100
101 #endif // DSD
+628
-0
dsd.c less more
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // dsd support
21
22 #include "squeezelite.h"
23
24 #if DSD
25
26 // use dsd2pcm from Sebastian Gesemann for conversion to pcm:
27 #include "./dsd2pcm/dsd2pcm.h"
28
29 extern log_level loglevel;
30
31 extern struct buffer *streambuf;
32 extern struct buffer *outputbuf;
33 extern struct streamstate stream;
34 extern struct outputstate output;
35 extern struct decodestate decode;
36 extern struct processstate process;
37
38 #define LOCK_S mutex_lock(streambuf->mutex)
39 #define UNLOCK_S mutex_unlock(streambuf->mutex)
40 #define LOCK_O mutex_lock(outputbuf->mutex)
41 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
42 #if PROCESS
43 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
44 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
45 #define LOCK_O_not_direct if (!decode.direct) mutex_lock(outputbuf->mutex)
46 #define UNLOCK_O_not_direct if (!decode.direct) mutex_unlock(outputbuf->mutex)
47 #define IF_DIRECT(x) if (decode.direct) { x }
48 #define IF_PROCESS(x) if (!decode.direct) { x }
49 #else
50 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
51 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
52 #define LOCK_O_not_direct
53 #define UNLOCK_O_not_direct
54 #define IF_DIRECT(x) { x }
55 #define IF_PROCESS(x)
56 #endif
57
58 #define BLOCK 4096 // expected size of dsd block
59 #define BLOCK_FRAMES BLOCK * BYTES_PER_FRAME
60 #define WRAP_BUF_SIZE 16
61
62 typedef enum { UNKNOWN=0, DSF, DSDIFF } dsd_type;
63
64 static bool dop = false; // local copy of output.has_dop to avoid holding output lock
65
66 struct dsd {
67 dsd_type type;
68 u32_t consume;
69 u32_t sample_rate;
70 u32_t channels;
71 u64_t sample_bytes;
72 u32_t block_size;
73 bool lsb_first;
74 dsd2pcm_ctx *dsd2pcm_ctx[2];
75 float *transfer[2];
76 };
77
78 static struct dsd *d;
79
80 static u64_t unpack64be(const u8_t *p) {
81 return
82 (u64_t)p[0] << 56 | (u64_t)p[1] << 48 | (u64_t)p[2] << 40 | (u64_t)p[3] << 32 |
83 (u64_t)p[4] << 24 | (u64_t)p[5] << 16 | (u64_t)p[6] << 8 | (u64_t)p[7];
84 }
85
86 static u64_t unpack64le(const u8_t *p) {
87 return
88 (u64_t)p[7] << 56 | (u64_t)p[6] << 48 | (u64_t)p[5] << 40 | (u64_t)p[4] << 32 |
89 (u64_t)p[3] << 24 | (u64_t)p[2] << 16 | (u64_t)p[1] << 8 | (u64_t)p[0];
90 }
91
92 static u32_t unpack32le(const u8_t *p) {
93 return
94 (u32_t)p[3] << 24 | (u32_t)p[2] << 16 | (u32_t)p[1] << 8 | (u32_t)p[0];
95 }
96
97 static int _read_header(void) {
98 unsigned bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
99 s32_t consume;
100
101 if (!d->type && bytes >= 4) {
102 if (!memcmp(streambuf->readp, "FRM8", 4)) {
103 d->type = DSDIFF;
104 } else if (!memcmp(streambuf->readp, "DSD ", 4)) {
105 d->type = DSF;
106 } else {
107 LOG_WARN("bad type");
108 return -1;
109 }
110 }
111
112 while (bytes >= 16) {
113 char id[5];
114 u64_t len = d->type == DSDIFF ? unpack64be(streambuf->readp + 4) : unpack64le(streambuf->readp + 4);
115 memcpy(id, streambuf->readp, 4);
116 id[4] = '\0';
117 consume = 0;
118
119 if (d->type == DSDIFF) {
120 if (!strcmp(id, "FRM8")) {
121 if (!memcmp(streambuf->readp + 12, "DSD ", 4)) {
122 consume = 16; // read into
123 } else {
124 LOG_WARN("bad dsdiff FRM8");
125 return -1;
126 }
127 }
128 if (!strcmp(id, "PROP") && !memcmp(streambuf->readp + 12, "SND ", 4)) {
129 consume = 16; // read into
130 }
131 if (!strcmp(id, "FVER")) {
132 LOG_INFO("DSDIFF version: %u.%u.%u.%u", *(streambuf->readp + 12), *(streambuf->readp + 13),
133 *(streambuf->readp + 14), *(streambuf->readp + 15));
134 }
135 if (!strcmp(id, "FS ")) {
136 d->sample_rate = unpackN((void *)(streambuf->readp + 12));
137 LOG_INFO("sample rate: %u", d->sample_rate);
138 }
139 if (!strcmp(id, "CHNL")) {
140 d->channels = unpackn((void *)(streambuf->readp + 12));
141 LOG_INFO("channels: %u", d->channels);
142 }
143 if (!strcmp(id, "DSD ")) {
144 LOG_INFO("found dsd len: " FMT_u64, len);
145 d->sample_bytes = len;
146 _buf_inc_readp(streambuf, 12);
147 bytes -= 12;
148 return 1; // got to the audio
149 }
150 }
151
152 if (d->type == DSF) {
153 if (!strcmp(id, "fmt ")) {
154 if (bytes >= len && bytes >= 52) {
155 u32_t version = unpack32le((void *)(streambuf->readp + 12));
156 u32_t format = unpack32le((void *)(streambuf->readp + 16));
157 LOG_INFO("DSF version: %u format: %u", version, format);
158 if (format != 0) {
159 LOG_WARN("only support DSD raw format");
160 return -1;
161 }
162 d->channels = unpack32le((void *)(streambuf->readp + 24));
163 d->sample_rate = unpack32le((void *)(streambuf->readp + 28));
164 d->lsb_first = (unpack32le((void *)(streambuf->readp + 32)) == 1);
165 d->sample_bytes = unpack64le((void *)(streambuf->readp + 36)) / 8;
166 d->block_size = unpack32le((void *)(streambuf->readp + 44));
167 LOG_INFO("channels: %u", d->channels);
168 LOG_INFO("sample rate: %u", d->sample_rate);
169 LOG_INFO("lsb first: %u", d->lsb_first);
170 LOG_INFO("sample bytes: " FMT_u64, d->sample_bytes);
171 LOG_INFO("block size: %u", d->block_size);
172 } else {
173 consume = -1; // come back later
174 }
175 }
176 if (!strcmp(id, "data")) {
177 LOG_INFO("found dsd len: " FMT_u64, len);
178 _buf_inc_readp(streambuf, 12);
179 bytes -= 12;
180 return 1; // got to the audio
181 }
182 }
183
184 // default to consuming whole chunk
185 if (!consume) {
186 consume = (s32_t)((d->type == DSDIFF) ? len + 12 : len);
187 }
188
189 if (bytes >= consume) {
190 LOG_DEBUG("id: %s len: " FMT_u64 " consume: %d", id, len, consume);
191 _buf_inc_readp(streambuf, consume);
192 bytes -= consume;
193 } else if (consume > 0) {
194 LOG_DEBUG("id: %s len: " FMT_u64 " consume: %d - partial consume: %u", id, len, consume, bytes);
195 _buf_inc_readp(streambuf, bytes);
196 d->consume = consume - bytes;
197 break;
198 } else {
199 break;
200 }
201 }
202
203 return 0;
204 }
205
206 static decode_state _decode_dsf(void) {
207
208 // samples in streambuf are interleaved on block basis
209 // we transfer whole blocks for all channels in one call and so itterate the while loop below to handle wraps
210
211 unsigned bytes = _buf_used(streambuf);
212 unsigned block_left = d->block_size;
213
214 unsigned bytes_per_frame = dop ? 2 : 1;
215
216 if (bytes < d->block_size * d->channels) {
217 LOG_INFO("stream too short"); // this can occur when scanning the track
218 return DECODE_COMPLETE;
219 }
220
221 IF_PROCESS(
222 process.in_frames = 0;
223 );
224
225 while (block_left) {
226
227 frames_t frames, out, count;
228 unsigned bytes_read;
229
230 u8_t *iptrl = (u8_t *)streambuf->readp;
231 u8_t *iptrr = (u8_t *)streambuf->readp + d->block_size;
232 u32_t *optr;
233
234 if (iptrr >= streambuf->wrap) {
235 iptrr -= streambuf->size;
236 }
237
238 bytes = min(block_left, min(streambuf->wrap - iptrl, streambuf->wrap - iptrr));
239
240 IF_DIRECT(
241 out = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
242 optr = (u32_t *)outputbuf->writep;
243 );
244 IF_PROCESS(
245 out = process.max_in_frames - process.in_frames;
246 optr = (u32_t *)(process.inbuf + process.in_frames * BYTES_PER_FRAME);
247 );
248
249 frames = min(bytes, d->sample_bytes) / bytes_per_frame;
250 if (frames == 0) {
251 if (dop && d->sample_bytes == 1 && bytes >= 2) {
252 // 1 byte left add a byte of silence and play
253 *(iptrl + 1) = *(iptrr + 1) = 0x69;
254 frames = 1;
255 } else {
256 // should not get here due to wrapping m/2 for dop should never result in 0 as header len is always even
257 LOG_INFO("frames got to zero");
258 return DECODE_COMPLETE;
259 }
260 }
261
262 frames = min(frames, out);
263 frames = min(frames, BLOCK);
264 bytes_read = frames * bytes_per_frame;
265
266 count = frames;
267
268 if (dop) {
269
270 if (d->channels == 1) {
271 if (d->lsb_first) {
272 while (count--) {
273 *(optr++) = dsd2pcm_bitreverse[*(iptrl)] << 16 | dsd2pcm_bitreverse[*(iptrl+1)] << 8;
274 *(optr++) = dsd2pcm_bitreverse[*(iptrl)] << 16 | dsd2pcm_bitreverse[*(iptrl+1)] << 8;
275 iptrl += 2;
276 }
277 } else {
278 while (count--) {
279 *(optr++) = *(iptrl) << 16 | *(iptrl+1) << 8;
280 *(optr++) = *(iptrl) << 16 | *(iptrl+1) << 8;
281 iptrl += 2;
282 }
283 }
284 } else {
285 if (d->lsb_first) {
286 while (count--) {
287 *(optr++) = dsd2pcm_bitreverse[*(iptrl)] << 16 | dsd2pcm_bitreverse[*(iptrl+1)] << 8;
288 *(optr++) = dsd2pcm_bitreverse[*(iptrr)] << 16 | dsd2pcm_bitreverse[*(iptrr+1)] << 8;
289 iptrl += 2;
290 iptrr += 2;
291 }
292 } else {
293 while (count--) {
294 *(optr++) = *(iptrl) << 16 | *(iptrl+1) << 8;
295 *(optr++) = *(iptrr) << 16 | *(iptrr+1) << 8;
296 iptrl += 2;
297 iptrr += 2;
298 }
299 }
300 }
301
302 } else {
303
304 if (d->channels == 1) {
305 float *iptrf = d->transfer[0];
306 dsd2pcm_translate(d->dsd2pcm_ctx[0], frames, iptrl, 1, d->lsb_first, iptrf, 1);
307 while (count--) {
308 double scaled = *iptrf++ * 0x7fffffff;
309 if (scaled > 2147483647.0) scaled = 2147483647.0;
310 if (scaled < -2147483648.0) scaled = -2147483648.0;
311 *optr++ = (s32_t)scaled;
312 *optr++ = (s32_t)scaled;
313 }
314 } else {
315 float *iptrfl = d->transfer[0];
316 float *iptrfr = d->transfer[1];
317 dsd2pcm_translate(d->dsd2pcm_ctx[0], frames, iptrl, 1, d->lsb_first, iptrfl, 1);
318 dsd2pcm_translate(d->dsd2pcm_ctx[1], frames, iptrr, 1, d->lsb_first, iptrfr, 1);
319 while (count--) {
320 double scaledl = *iptrfl++ * 0x7fffffff;
321 double scaledr = *iptrfr++ * 0x7fffffff;
322 if (scaledl > 2147483647.0) scaledl = 2147483647.0;
323 if (scaledl < -2147483648.0) scaledl = -2147483648.0;
324 if (scaledr > 2147483647.0) scaledr = 2147483647.0;
325 if (scaledr < -2147483648.0) scaledr = -2147483648.0;
326 *optr++ = (s32_t)scaledl;
327 *optr++ = (s32_t)scaledr;
328 }
329 }
330
331 }
332
333 _buf_inc_readp(streambuf, bytes_read);
334
335 block_left -= bytes_read;
336
337 if (d->sample_bytes > bytes_read) {
338 d->sample_bytes -= bytes_read;
339 } else {
340 LOG_INFO("end of track samples");
341 block_left = 0;
342 d->sample_bytes = 0;
343 }
344
345 IF_DIRECT(
346 _buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
347 );
348 IF_PROCESS(
349 process.in_frames += frames;
350 );
351
352 LOG_SDEBUG("write %u frames", frames);
353 }
354
355 // skip the other channel blocks
356 // the right channel has already been read and is guarenteed to be in streambuf so can be skipped immediately
357 if (d->channels > 1) {
358 _buf_inc_readp(streambuf, d->block_size);
359 }
360 if (d->channels > 2) {
361 d->consume = d->block_size * (d->channels - 2);
362 }
363
364 return DECODE_RUNNING;
365 }
366
367 static decode_state _decode_dsdiff(void) {
368
369 // samples in streambuf are interleaved on byte per channel
370 // we process as little as necessary per call and only need to handle frames wrapping round streambuf
371
372 unsigned bytes_per_frame, bytes_read;
373 frames_t out, frames, count;
374 u8_t *iptr;
375 u32_t *optr;
376 u8_t tmp[WRAP_BUF_SIZE];
377
378 unsigned bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
379
380 IF_DIRECT(
381 out = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
382 );
383 IF_PROCESS(
384 out = process.max_in_frames;
385 );
386
387 if (dop) {
388 bytes_per_frame = d->channels * 2;
389 } else {
390 bytes_per_frame = d->channels;
391 out = min(out, BLOCK);
392 }
393
394 frames = min(min(bytes, d->sample_bytes) / bytes_per_frame, out);
395 bytes_read = frames * bytes_per_frame;
396
397 iptr = (u8_t *)streambuf->readp;
398
399 IF_DIRECT(
400 optr = (u32_t *)outputbuf->writep;
401 );
402 IF_PROCESS(
403 optr = (u32_t *)process.inbuf;
404 );
405
406 // handle wrap around end of streambuf and partial dop frame at end of stream
407 if (!frames && bytes < bytes_per_frame) {
408 memset(tmp, 0x69, WRAP_BUF_SIZE); // 0x69 = dsd silence
409 memcpy(tmp, streambuf->readp, bytes);
410 if (_buf_used(streambuf) > bytes_per_frame) {
411 memcpy(tmp + bytes, streambuf->buf, bytes_per_frame - bytes);
412 bytes_read = bytes_per_frame;
413 } else {
414 bytes_read = bytes;
415 }
416 iptr = tmp;
417 frames = 1;
418 }
419
420 count = frames;
421
422 if (dop) {
423
424 if (d->channels == 1) {
425 while (count--) {
426 *(optr++) = *(iptr) << 16 | *(iptr+1) << 8;
427 *(optr++) = *(iptr) << 16 | *(iptr+1) << 8;
428 iptr += bytes_per_frame;
429 }
430 } else {
431 while (count--) {
432 *(optr++) = *(iptr ) << 16 | *(iptr + d->channels) << 8;
433 *(optr++) = *(iptr+1) << 16 | *(iptr + d->channels + 1) << 8;
434 iptr += bytes_per_frame;
435 }
436 }
437
438 } else {
439
440 if (d->channels == 1) {
441 float *iptrf = d->transfer[0];
442 dsd2pcm_translate(d->dsd2pcm_ctx[0], frames, iptr, 1, 0, iptrf, 1);
443 while (count--) {
444 double scaled = *iptrf++ * 0x7fffffff;
445 if (scaled > 2147483647.0) scaled = 2147483647.0;
446 if (scaled < -2147483648.0) scaled = -2147483648.0;
447 *optr++ = (s32_t)scaled;
448 *optr++ = (s32_t)scaled;
449 }
450 } else {
451 float *iptrfl = d->transfer[0];
452 float *iptrfr = d->transfer[1];
453 dsd2pcm_translate(d->dsd2pcm_ctx[0], frames, iptr, d->channels, 0, iptrfl, 1);
454 dsd2pcm_translate(d->dsd2pcm_ctx[1], frames, iptr + 1, d->channels, 0, iptrfr, 1);
455 while (count--) {
456 double scaledl = *iptrfl++ * 0x7fffffff;
457 double scaledr = *iptrfr++ * 0x7fffffff;
458 if (scaledl > 2147483647.0) scaledl = 2147483647.0;
459 if (scaledl < -2147483648.0) scaledl = -2147483648.0;
460 if (scaledr > 2147483647.0) scaledr = 2147483647.0;
461 if (scaledr < -2147483648.0) scaledr = -2147483648.0;
462 *optr++ = (s32_t)scaledl;
463 *optr++ = (s32_t)scaledr;
464 }
465 }
466
467 }
468
469 _buf_inc_readp(streambuf, bytes_read);
470
471 if (d->sample_bytes > bytes_read) {
472 d->sample_bytes -= bytes_read;
473 } else {
474 LOG_INFO("end of track samples");
475 d->sample_bytes = 0;
476 }
477
478 IF_DIRECT(
479 _buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
480 );
481 IF_PROCESS(
482 process.in_frames = frames;
483 );
484
485 LOG_SDEBUG("write %u frames", frames);
486
487 return DECODE_RUNNING;
488 }
489
490
491 static decode_state dsd_decode(void) {
492 decode_state ret;
493
494 LOCK_S;
495
496 if ((stream.state <= DISCONNECT && !_buf_used(streambuf)) || (!decode.new_stream && d->sample_bytes == 0)) {
497 UNLOCK_S;
498 return DECODE_COMPLETE;
499 }
500
501 if (d->consume) {
502 unsigned consume = min(d->consume, min(_buf_used(streambuf), _buf_cont_read(streambuf)));
503 LOG_DEBUG("consume: %u of %u", consume, d->consume);
504 _buf_inc_readp(streambuf, consume);
505 d->consume -= consume;
506 if (d->consume) {
507 UNLOCK_S;
508 return DECODE_RUNNING;
509 }
510 }
511
512 if (decode.new_stream) {
513 int r = _read_header();
514 if (r < 1) {
515 UNLOCK_S;
516 return DECODE_ERROR;
517 }
518 if (r == 0) {
519 UNLOCK_S;
520 return DECODE_RUNNING;
521 }
522 // otherwise got to start of audio
523
524 LOCK_O;
525
526 LOG_INFO("setting track_start");
527 output.track_start = outputbuf->writep;
528
529 dop = output.has_dop;
530
531 if (dop && d->sample_rate / 16 > output.supported_rates[0]) {
532 LOG_INFO("DOP sample rate too high for device - converting to PCM");
533 dop = false;
534 }
535
536 if (dop) {
537 LOG_INFO("DOP output");
538 output.next_dop = true;
539 output.next_sample_rate = d->sample_rate / 16;
540 output.fade = FADE_INACTIVE;
541 } else {
542 LOG_INFO("DSD to PCM output");
543 output.next_dop = false;
544 output.next_sample_rate = decode_newstream(d->sample_rate / 8, output.supported_rates);
545 if (output.fade_mode) _checkfade(true);
546 }
547
548 decode.new_stream = false;
549
550 UNLOCK_O;
551 }
552
553 LOCK_O_direct;
554
555 switch (d->type) {
556 case DSF:
557 ret = _decode_dsf();
558 break;
559 case DSDIFF:
560 ret = _decode_dsdiff();
561 break;
562 default:
563 ret = DECODE_ERROR;
564 }
565
566 UNLOCK_O_direct;
567 UNLOCK_S;
568
569 return ret;
570 }
571
572 static void dsd_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
573 d->type = UNKNOWN;
574
575 if (!d->dsd2pcm_ctx[0]) {
576 d->dsd2pcm_ctx[0] = dsd2pcm_init();
577 d->dsd2pcm_ctx[1] = dsd2pcm_init();
578 } else {
579 dsd2pcm_reset(d->dsd2pcm_ctx[0]);
580 dsd2pcm_reset(d->dsd2pcm_ctx[1]);
581 }
582 if (!d->transfer[1]) {
583 d->transfer[0] = malloc(sizeof(float) * BLOCK);
584 d->transfer[1] = malloc(sizeof(float) * BLOCK);
585 }
586 }
587
588 static void dsd_close(void) {
589 if (d->dsd2pcm_ctx[0]) {
590 dsd2pcm_destroy(d->dsd2pcm_ctx[0]);
591 dsd2pcm_destroy(d->dsd2pcm_ctx[1]);
592 d->dsd2pcm_ctx[0] = NULL;
593 d->dsd2pcm_ctx[1] = NULL;
594 }
595 if (d->transfer[0]) {
596 free(d->transfer[0]);
597 free(d->transfer[1]);
598 d->transfer[0] = NULL;
599 d->transfer[1] = NULL;
600 }
601 }
602
603 struct codec *register_dsd(void) {
604 static struct codec ret = {
605 'd', // id
606 "dsf,dff", // types
607 BLOCK * 2, // min read
608 BLOCK_FRAMES,// min space
609 dsd_open, // open
610 dsd_close, // close
611 dsd_decode, // decode
612 };
613
614 d = malloc(sizeof(struct dsd));
615 if (!d) {
616 return NULL;
617 }
618
619 memset(d, 0, sizeof(struct dsd));
620
621 dsd2pcm_precalc();
622
623 LOG_INFO("using dsd to decode dsf,dff");
624 return &ret;
625 }
626
627 #endif // DSD
0 Copyright 2009, 2011 Sebastian Gesemann. All rights reserved.
1
2 Redistribution and use in source and binary forms, with or without modification, are
3 permitted provided that the following conditions are met:
4
5 1. Redistributions of source code must retain the above copyright notice, this list of
6 conditions and the following disclaimer.
7
8 2. Redistributions in binary form must reproduce the above copyright notice, this list
9 of conditions and the following disclaimer in the documentation and/or other materials
10 provided with the distribution.
11
12 THIS SOFTWARE IS PROVIDED BY SEBASTIAN GESEMANN ''AS IS'' AND ANY EXPRESS OR IMPLIED
13 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
14 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEBASTIAN GESEMANN OR
15 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
16 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
20 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
22 The views and conclusions contained in the software and documentation are those of the
23 authors and should not be interpreted as representing official policies, either expressed
24 or implied, of Sebastian Gesemann.
0 /*
1
2 Copyright 2009, 2011 Sebastian Gesemann. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without modification, are
5 permitted provided that the following conditions are met:
6
7 1. Redistributions of source code must retain the above copyright notice, this list of
8 conditions and the following disclaimer.
9
10 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 of conditions and the following disclaimer in the documentation and/or other materials
12 provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY SEBASTIAN GESEMANN ''AS IS'' AND ANY EXPRESS OR IMPLIED
15 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEBASTIAN GESEMANN OR
17 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24 The views and conclusions contained in the software and documentation are those of the
25 authors and should not be interpreted as representing official policies, either expressed
26 or implied, of Sebastian Gesemann.
27
28 ----
29
30 Additions (c) Adrian Smith, 2013 under same licence terms:
31 - expose bitreverse array as dsd2pcm_bitreverse
32 - expose precalc function as dsd2pcm_precalc to allow it to be initalised
33
34 */
35
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "dsd2pcm.h"
40
41 #define HTAPS 48 /* number of FIR constants */
42 #define FIFOSIZE 16 /* must be a power of two */
43 #define FIFOMASK (FIFOSIZE-1) /* bit mask for FIFO offsets */
44 #define CTABLES ((HTAPS+7)/8) /* number of "8 MACs" lookup tables */
45
46 #if FIFOSIZE*8 < HTAPS*2
47 #error "FIFOSIZE too small"
48 #endif
49
50 /*
51 * Properties of this 96-tap lowpass filter when applied on a signal
52 * with sampling rate of 44100*64 Hz:
53 *
54 * () has a delay of 17 microseconds.
55 *
56 * () flat response up to 48 kHz
57 *
58 * () if you downsample afterwards by a factor of 8, the
59 * spectrum below 70 kHz is practically alias-free.
60 *
61 * () stopband rejection is about 160 dB
62 *
63 * The coefficient tables ("ctables") take only 6 Kibi Bytes and
64 * should fit into a modern processor's fast cache.
65 */
66
67 /*
68 * The 2nd half (48 coeffs) of a 96-tap symmetric lowpass filter
69 */
70 static const double htaps[HTAPS] = {
71 0.09950731974056658,
72 0.09562845727714668,
73 0.08819647126516944,
74 0.07782552527068175,
75 0.06534876523171299,
76 0.05172629311427257,
77 0.0379429484910187,
78 0.02490921351762261,
79 0.0133774746265897,
80 0.003883043418804416,
81 -0.003284703416210726,
82 -0.008080250212687497,
83 -0.01067241812471033,
84 -0.01139427235000863,
85 -0.0106813877974587,
86 -0.009007905078766049,
87 -0.006828859761015335,
88 -0.004535184322001496,
89 -0.002425035959059578,
90 -0.0006922187080790708,
91 0.0005700762133516592,
92 0.001353838005269448,
93 0.001713709169690937,
94 0.001742046839472948,
95 0.001545601648013235,
96 0.001226696225277855,
97 0.0008704322683580222,
98 0.0005381636200535649,
99 0.000266446345425276,
100 7.002968738383528e-05,
101 -5.279407053811266e-05,
102 -0.0001140625650874684,
103 -0.0001304796361231895,
104 -0.0001189970287491285,
105 -9.396247155265073e-05,
106 -6.577634378272832e-05,
107 -4.07492895872535e-05,
108 -2.17407957554587e-05,
109 -9.163058931391722e-06,
110 -2.017460145032201e-06,
111 1.249721855219005e-06,
112 2.166655190537392e-06,
113 1.930520892991082e-06,
114 1.319400334374195e-06,
115 7.410039764949091e-07,
116 3.423230509967409e-07,
117 1.244182214744588e-07,
118 3.130441005359396e-08
119 };
120
121 static float ctables[CTABLES][256];
122 unsigned char dsd2pcm_bitreverse[256];
123 static int precalculated = 0;
124
125 void dsd2pcm_precalc(void)
126 {
127 int t, e, m, k;
128 double acc;
129 if (precalculated) return;
130 for (t=0, e=0; t<256; ++t) {
131 dsd2pcm_bitreverse[t] = e;
132 for (m=128; m && !((e^=m)&m); m>>=1)
133 ;
134 }
135 for (t=0; t<CTABLES; ++t) {
136 k = HTAPS - t*8;
137 if (k>8) k=8;
138 for (e=0; e<256; ++e) {
139 acc = 0.0;
140 for (m=0; m<k; ++m) {
141 acc += (((e >> (7-m)) & 1)*2-1) * htaps[t*8+m];
142 }
143 ctables[CTABLES-1-t][e] = (float)acc;
144 }
145 }
146 precalculated = 1;
147 }
148
149 struct dsd2pcm_ctx_s
150 {
151 unsigned char fifo[FIFOSIZE];
152 unsigned fifopos;
153 };
154
155 extern dsd2pcm_ctx* dsd2pcm_init()
156 {
157 dsd2pcm_ctx* ptr;
158 if (!precalculated) dsd2pcm_precalc();
159 ptr = (dsd2pcm_ctx*) malloc(sizeof(dsd2pcm_ctx));
160 if (ptr) dsd2pcm_reset(ptr);
161 return ptr;
162 }
163
164 extern void dsd2pcm_destroy(dsd2pcm_ctx* ptr)
165 {
166 free(ptr);
167 }
168
169 extern dsd2pcm_ctx* dsd2pcm_clone(dsd2pcm_ctx* ptr)
170 {
171 dsd2pcm_ctx* p2;
172 p2 = (dsd2pcm_ctx*) malloc(sizeof(dsd2pcm_ctx));
173 if (p2) {
174 memcpy(p2,ptr,sizeof(dsd2pcm_ctx));
175 }
176 return p2;
177 }
178
179 extern void dsd2pcm_reset(dsd2pcm_ctx* ptr)
180 {
181 int i;
182 for (i=0; i<FIFOSIZE; ++i)
183 ptr->fifo[i] = 0x69; /* my favorite silence pattern */
184 ptr->fifopos = 0;
185 /* 0x69 = 01101001
186 * This pattern "on repeat" makes a low energy 352.8 kHz tone
187 * and a high energy 1.0584 MHz tone which should be filtered
188 * out completely by any playback system --> silence
189 */
190 }
191
192 extern void dsd2pcm_translate(
193 dsd2pcm_ctx* ptr,
194 size_t samples,
195 const unsigned char *src, ptrdiff_t src_stride,
196 int lsbf,
197 float *dst, ptrdiff_t dst_stride)
198 {
199 unsigned ffp;
200 unsigned i;
201 unsigned bite1, bite2;
202 unsigned char* p;
203 double acc;
204 ffp = ptr->fifopos;
205 lsbf = lsbf ? 1 : 0;
206 while (samples-- > 0) {
207 bite1 = *src & 0xFFu;
208 if (lsbf) bite1 = dsd2pcm_bitreverse[bite1];
209 ptr->fifo[ffp] = bite1; src += src_stride;
210 p = ptr->fifo + ((ffp-CTABLES) & FIFOMASK);
211 *p = dsd2pcm_bitreverse[*p & 0xFF];
212 acc = 0;
213 for (i=0; i<CTABLES; ++i) {
214 bite1 = ptr->fifo[(ffp -i) & FIFOMASK] & 0xFF;
215 bite2 = ptr->fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK] & 0xFF;
216 acc += ctables[i][bite1] + ctables[i][bite2];
217 }
218 *dst = (float)acc; dst += dst_stride;
219 ffp = (ffp + 1) & FIFOMASK;
220 }
221 ptr->fifopos = ffp;
222 }
223
0 /*
1
2 Copyright 2009, 2011 Sebastian Gesemann. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without modification, are
5 permitted provided that the following conditions are met:
6
7 1. Redistributions of source code must retain the above copyright notice, this list of
8 conditions and the following disclaimer.
9
10 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 of conditions and the following disclaimer in the documentation and/or other materials
12 provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY SEBASTIAN GESEMANN ''AS IS'' AND ANY EXPRESS OR IMPLIED
15 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEBASTIAN GESEMANN OR
17 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24 The views and conclusions contained in the software and documentation are those of the
25 authors and should not be interpreted as representing official policies, either expressed
26 or implied, of Sebastian Gesemann.
27
28 ----
29
30 Marked additions (c) Adrian Smith, 2013 under same licence terms
31
32 */
33
34 #ifndef DSD2PCM_H_INCLUDED
35 #define DSD2PCM_H_INCLUDED
36
37 #include <stddef.h>
38 #include <string.h>
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 struct dsd2pcm_ctx_s;
45
46 typedef struct dsd2pcm_ctx_s dsd2pcm_ctx;
47
48 /**
49 * initializes a "dsd2pcm engine" for one channel
50 * (precomputes tables and allocates memory)
51 *
52 * This is the only function that is not thread-safe in terms of the
53 * POSIX thread-safety definition because it modifies global state
54 * (lookup tables are computed during the first call)
55 */
56 extern dsd2pcm_ctx* dsd2pcm_init(void);
57
58 /**
59 * deinitializes a "dsd2pcm engine"
60 * (releases memory, don't forget!)
61 */
62 extern void dsd2pcm_destroy(dsd2pcm_ctx *ctx);
63
64 /**
65 * clones the context and returns a pointer to the
66 * newly allocated copy
67 */
68 extern dsd2pcm_ctx* dsd2pcm_clone(dsd2pcm_ctx *ctx);
69
70 /**
71 * resets the internal state for a fresh new stream
72 */
73 extern void dsd2pcm_reset(dsd2pcm_ctx *ctx);
74
75 /**
76 * "translates" a stream of octets to a stream of floats
77 * (8:1 decimation)
78 * @param ctx -- pointer to abstract context (buffers)
79 * @param samples -- number of octets/samples to "translate"
80 * @param src -- pointer to first octet (input)
81 * @param src_stride -- src pointer increment
82 * @param lsbitfirst -- bitorder, 0=msb first, 1=lsbfirst
83 * @param dst -- pointer to first float (output)
84 * @param dst_stride -- dst pointer increment
85 */
86 extern void dsd2pcm_translate(dsd2pcm_ctx *ctx,
87 size_t samples,
88 const unsigned char *src, ptrdiff_t src_stride,
89 int lsbitfirst,
90 float *dst, ptrdiff_t dst_stride);
91
92 /**
93 * Additions by Adrian Smith (c) 2013 for Squeezelite
94 */
95 extern unsigned char dsd2pcm_bitreverse[];
96
97 extern void dsd2pcm_precalc(void);
98 /**
99 * End of addition
100 */
101
102 #ifdef __cplusplus
103 } /* extern "C" */
104 #endif
105
106 #endif /* include guard DSD2PCM_H_INCLUDED */
107
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 #include <neaacdec.h>
23
24 #define WRAPBUF_LEN 2048
25
26 struct chunk_table {
27 u32_t sample, offset;
28 };
29
30 struct faad {
31 NeAACDecHandle hAac;
32 u8_t type;
33 // following used for mp4 only
34 u32_t consume;
35 u32_t pos;
36 u32_t sample;
37 u32_t nextchunk;
38 void *stsc;
39 u32_t skip;
40 u64_t samples;
41 u64_t sttssamples;
42 bool empty;
43 struct chunk_table *chunkinfo;
44 // faad symbols to be dynamically loaded
45 #if !LINKALL
46 NeAACDecConfigurationPtr (* NeAACDecGetCurrentConfiguration)(NeAACDecHandle);
47 unsigned char (* NeAACDecSetConfiguration)(NeAACDecHandle, NeAACDecConfigurationPtr);
48 NeAACDecHandle (* NeAACDecOpen)(void);
49 void (* NeAACDecClose)(NeAACDecHandle);
50 long (* NeAACDecInit)(NeAACDecHandle, unsigned char *, unsigned long, unsigned long *, unsigned char *);
51 char (* NeAACDecInit2)(NeAACDecHandle, unsigned char *pBuffer, unsigned long, unsigned long *, unsigned char *);
52 void *(* NeAACDecDecode)(NeAACDecHandle, NeAACDecFrameInfo *, unsigned char *, unsigned long);
53 char *(* NeAACDecGetErrorMessage)(unsigned char);
54 #endif
55 };
56
57 static struct faad *a;
58
59 extern log_level loglevel;
60
61 extern struct buffer *streambuf;
62 extern struct buffer *outputbuf;
63 extern struct streamstate stream;
64 extern struct outputstate output;
65 extern struct decodestate decode;
66 extern struct processstate process;
67
68 #define LOCK_S mutex_lock(streambuf->mutex)
69 #define UNLOCK_S mutex_unlock(streambuf->mutex)
70 #define LOCK_O mutex_lock(outputbuf->mutex)
71 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
72 #if PROCESS
73 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
74 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
75 #define IF_DIRECT(x) if (decode.direct) { x }
76 #define IF_PROCESS(x) if (!decode.direct) { x }
77 #else
78 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
79 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
80 #define IF_DIRECT(x) { x }
81 #define IF_PROCESS(x)
82 #endif
83
84 #if LINKALL
85 #define NEAAC(h, fn, ...) (NeAACDec ## fn)(__VA_ARGS__)
86 #else
87 #define NEAAC(h, fn, ...) (h)->NeAACDec##fn(__VA_ARGS__)
88 #endif
89
90 // minimal code for mp4 file parsing to extract audio config and find media data
91
92 // adapted from faad2/common/mp4ff
93 u32_t mp4_desc_length(u8_t **buf) {
94 u8_t b;
95 u8_t num_bytes = 0;
96 u32_t length = 0;
97
98 do {
99 b = **buf;
100 *buf += 1;
101 num_bytes++;
102 length = (length << 7) | (b & 0x7f);
103 } while ((b & 0x80) && num_bytes < 4);
104
105 return length;
106 }
107
108 // read mp4 header to extract config data
109 static int read_mp4_header(unsigned long *samplerate_p, unsigned char *channels_p) {
110 size_t bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
111 char type[5];
112 u32_t len;
113
114 while (bytes >= 8) {
115 // count trak to find the first playable one
116 static unsigned trak, play;
117 u32_t consume;
118
119 len = unpackN((u32_t *)streambuf->readp);
120 memcpy(type, streambuf->readp + 4, 4);
121 type[4] = '\0';
122
123 if (!strcmp(type, "moov")) {
124 trak = 0;
125 play = 0;
126 }
127 if (!strcmp(type, "trak")) {
128 trak++;
129 }
130
131 // extract audio config from within esds and pass to DecInit2
132 if (!strcmp(type, "esds") && bytes > len) {
133 unsigned config_len;
134 u8_t *ptr = streambuf->readp + 12;
135 if (*ptr++ == 0x03) {
136 mp4_desc_length(&ptr);
137 ptr += 4;
138 } else {
139 ptr += 3;
140 }
141 mp4_desc_length(&ptr);
142 ptr += 13;
143 if (*ptr++ != 0x05) {
144 LOG_WARN("error parsing esds");
145 return -1;
146 }
147 config_len = mp4_desc_length(&ptr);
148 if (NEAAC(a, Init2, a->hAac, ptr, config_len, samplerate_p, channels_p) == 0) {
149 LOG_DEBUG("playable aac track: %u", trak);
150 play = trak;
151 }
152 }
153
154 // extract the total number of samples from stts
155 if (!strcmp(type, "stts") && bytes > len) {
156 u32_t i;
157 u8_t *ptr = streambuf->readp + 12;
158 u32_t entries = unpackN((u32_t *)ptr);
159 ptr += 4;
160 for (i = 0; i < entries; ++i) {
161 u32_t count = unpackN((u32_t *)ptr);
162 u32_t size = unpackN((u32_t *)(ptr + 4));
163 a->sttssamples += count * size;
164 ptr += 8;
165 }
166 LOG_DEBUG("total number of samples contained in stts: " FMT_u64, a->sttssamples);
167 }
168
169 // stash sample to chunk info, assume it comes before stco
170 if (!strcmp(type, "stsc") && bytes > len && !a->chunkinfo) {
171 a->stsc = malloc(len - 12);
172 if (a->stsc == NULL) {
173 LOG_WARN("malloc fail");
174 return -1;
175 }
176 memcpy(a->stsc, streambuf->readp + 12, len - 12);
177 }
178
179 // build offsets table from stco and stored stsc
180 if (!strcmp(type, "stco") && bytes > len && play == trak) {
181 u32_t i;
182 // extract chunk offsets
183 u8_t *ptr = streambuf->readp + 12;
184 u32_t entries = unpackN((u32_t *)ptr);
185 ptr += 4;
186 a->chunkinfo = malloc(sizeof(struct chunk_table) * (entries + 1));
187 if (a->chunkinfo == NULL) {
188 LOG_WARN("malloc fail");
189 return -1;
190 }
191 for (i = 0; i < entries; ++i) {
192 a->chunkinfo[i].offset = unpackN((u32_t *)ptr);
193 a->chunkinfo[i].sample = 0;
194 ptr += 4;
195 }
196 a->chunkinfo[i].sample = 0;
197 a->chunkinfo[i].offset = 0;
198 // fill in first sample id for each chunk from stored stsc
199 if (a->stsc) {
200 u32_t stsc_entries = unpackN((u32_t *)a->stsc);
201 u32_t sample = 0;
202 u32_t last = 0, last_samples = 0;
203 u8_t *ptr = (u8_t *)a->stsc + 4;
204 while (stsc_entries--) {
205 u32_t first = unpackN((u32_t *)ptr);
206 u32_t samples = unpackN((u32_t *)(ptr + 4));
207 if (last) {
208 for (i = last - 1; i < first - 1; ++i) {
209 a->chunkinfo[i].sample = sample;
210 sample += last_samples;
211 }
212 }
213 if (stsc_entries == 0) {
214 for (i = first - 1; i < entries; ++i) {
215 a->chunkinfo[i].sample = sample;
216 sample += samples;
217 }
218 }
219 last = first;
220 last_samples = samples;
221 ptr += 12;
222 }
223 free(a->stsc);
224 a->stsc = NULL;
225 }
226 }
227
228 // found media data, advance to start of first chunk and return
229 if (!strcmp(type, "mdat")) {
230 _buf_inc_readp(streambuf, 8);
231 a->pos += 8;
232 bytes -= 8;
233 if (play) {
234 LOG_DEBUG("type: mdat len: %u pos: %u", len, a->pos);
235 if (a->chunkinfo && a->chunkinfo[0].offset > a->pos) {
236 u32_t skip = a->chunkinfo[0].offset - a->pos;
237 LOG_DEBUG("skipping: %u", skip);
238 if (skip <= bytes) {
239 _buf_inc_readp(streambuf, skip);
240 a->pos += skip;
241 } else {
242 a->consume = skip;
243 }
244 }
245 a->sample = a->nextchunk = 1;
246 return 1;
247 } else {
248 LOG_DEBUG("type: mdat len: %u, no playable track found", len);
249 return -1;
250 }
251 }
252
253 // parse key-value atoms within ilst ---- entries to get encoder padding within iTunSMPB entry for gapless
254 if (!strcmp(type, "----") && bytes > len) {
255 u8_t *ptr = streambuf->readp + 8;
256 u32_t remain = len - 8, size;
257 if (!memcmp(ptr + 4, "mean", 4) && (size = unpackN((u32_t *)ptr)) < remain) {
258 ptr += size; remain -= size;
259 }
260 if (!memcmp(ptr + 4, "name", 4) && (size = unpackN((u32_t *)ptr)) < remain && !memcmp(ptr + 12, "iTunSMPB", 8)) {
261 ptr += size; remain -= size;
262 }
263 if (!memcmp(ptr + 4, "data", 4) && remain > 16 + 48) {
264 // data is stored as hex strings: 0 start end samples
265 u32_t b, c; u64_t d;
266 if (sscanf((const char *)(ptr + 16), "%x %x %x " FMT_x64, &b, &b, &c, &d) == 4) {
267 LOG_DEBUG("iTunSMPB start: %u end: %u samples: " FMT_u64, b, c, d);
268 if (a->sttssamples && a->sttssamples < b + c + d) {
269 LOG_DEBUG("reducing samples as stts count is less");
270 d = a->sttssamples - (b + c);
271 }
272 a->skip = b;
273 a->samples = d;
274 }
275 }
276 }
277
278 // default to consuming entire box
279 consume = len;
280
281 // read into these boxes so reduce consume
282 if (!strcmp(type, "moov") || !strcmp(type, "trak") || !strcmp(type, "mdia") || !strcmp(type, "minf") || !strcmp(type, "stbl") ||
283 !strcmp(type, "udta") || !strcmp(type, "ilst")) {
284 consume = 8;
285 }
286 // special cases which mix mix data in the enclosing box which we want to read into
287 if (!strcmp(type, "stsd")) consume = 16;
288 if (!strcmp(type, "mp4a")) consume = 36;
289 if (!strcmp(type, "meta")) consume = 12;
290
291 // consume rest of box if it has been parsed (all in the buffer) or is not one we want to parse
292 if (bytes >= consume) {
293 LOG_DEBUG("type: %s len: %u consume: %u", type, len, consume);
294 _buf_inc_readp(streambuf, consume);
295 a->pos += consume;
296 bytes -= consume;
297 } else if ( !(!strcmp(type, "esds") || !strcmp(type, "stts") || !strcmp(type, "stsc") ||
298 !strcmp(type, "stco") || !strcmp(type, "----")) ) {
299 LOG_DEBUG("type: %s len: %u consume: %u - partial consume: %u", type, len, consume, bytes);
300 _buf_inc_readp(streambuf, bytes);
301 a->pos += bytes;
302 a->consume = consume - bytes;
303 break;
304 } else {
305 break;
306 }
307 }
308
309 return 0;
310 }
311
312 static decode_state faad_decode(void) {
313 size_t bytes_total;
314 size_t bytes_wrap;
315 NeAACDecFrameInfo info;
316 s32_t *iptr;
317 bool endstream;
318 frames_t frames;
319
320 LOCK_S;
321 bytes_total = _buf_used(streambuf);
322 bytes_wrap = min(bytes_total, _buf_cont_read(streambuf));
323
324 if (stream.state <= DISCONNECT && !bytes_total) {
325 UNLOCK_S;
326 return DECODE_COMPLETE;
327 }
328
329 if (a->consume) {
330 u32_t consume = min(a->consume, bytes_wrap);
331 LOG_DEBUG("consume: %u of %u", consume, a->consume);
332 _buf_inc_readp(streambuf, consume);
333 a->pos += consume;
334 a->consume -= consume;
335 UNLOCK_S;
336 return DECODE_RUNNING;
337 }
338
339 if (decode.new_stream) {
340 int found = 0;
341 static unsigned char channels;
342 static unsigned long samplerate;
343
344 if (a->type == '2') {
345
346 // adts stream - seek for header
347 while (bytes_wrap >= 2 && (*(streambuf->readp) != 0xFF || (*(streambuf->readp + 1) & 0xF6) != 0xF0)) {
348 _buf_inc_readp(streambuf, 1);
349 bytes_total--;
350 bytes_wrap--;
351 }
352
353 if (bytes_wrap >= 2) {
354 long n = NEAAC(a, Init, a->hAac, streambuf->readp, bytes_wrap, &samplerate, &channels);
355 if (n < 0) {
356 found = -1;
357 } else {
358 _buf_inc_readp(streambuf, n);
359 found = 1;
360 }
361 }
362
363 } else {
364
365 // mp4 - read header
366 found = read_mp4_header(&samplerate, &channels);
367 }
368
369 if (found == 1) {
370
371 LOG_INFO("samplerate: %u channels: %u", samplerate, channels);
372 bytes_total = _buf_used(streambuf);
373 bytes_wrap = min(bytes_total, _buf_cont_read(streambuf));
374
375 LOCK_O;
376 LOG_INFO("setting track_start");
377 output.next_sample_rate = decode_newstream(samplerate, output.supported_rates);
378 IF_DSD( output.next_dop = false; )
379 output.track_start = outputbuf->writep;
380 if (output.fade_mode) _checkfade(true);
381 decode.new_stream = false;
382 UNLOCK_O;
383
384 } else if (found == -1) {
385
386 LOG_WARN("error reading stream header");
387 UNLOCK_S;
388 return DECODE_ERROR;
389
390 } else {
391
392 // not finished header parsing come back next time
393 UNLOCK_S;
394 return DECODE_RUNNING;
395 }
396 }
397
398 if (bytes_wrap < WRAPBUF_LEN && bytes_total > WRAPBUF_LEN) {
399
400 // make a local copy of frames which may have wrapped round the end of streambuf
401 u8_t buf[WRAPBUF_LEN];
402 memcpy(buf, streambuf->readp, bytes_wrap);
403 memcpy(buf + bytes_wrap, streambuf->buf, WRAPBUF_LEN - bytes_wrap);
404
405 iptr = NEAAC(a, Decode, a->hAac, &info, buf, WRAPBUF_LEN);
406
407 } else {
408
409 iptr = NEAAC(a, Decode, a->hAac, &info, streambuf->readp, bytes_wrap);
410 }
411
412 if (info.error) {
413 LOG_WARN("error: %u %s", info.error, NEAAC(a, GetErrorMessage, info.error));
414 }
415
416 endstream = false;
417
418 // mp4 end of chunk - skip to next offset
419 if (a->chunkinfo && a->chunkinfo[a->nextchunk].offset && a->sample++ == a->chunkinfo[a->nextchunk].sample) {
420
421 if (a->chunkinfo[a->nextchunk].offset > a->pos) {
422 u32_t skip = a->chunkinfo[a->nextchunk].offset - a->pos;
423 if (skip != info.bytesconsumed) {
424 LOG_DEBUG("skipping to next chunk pos: %u consumed: %u != skip: %u", a->pos, info.bytesconsumed, skip);
425 }
426 if (bytes_total >= skip) {
427 _buf_inc_readp(streambuf, skip);
428 a->pos += skip;
429 } else {
430 a->consume = skip;
431 }
432 a->nextchunk++;
433 } else {
434 LOG_ERROR("error: need to skip backwards!");
435 endstream = true;
436 }
437
438 // adts and mp4 when not at end of chunk
439 } else if (info.bytesconsumed != 0) {
440
441 _buf_inc_readp(streambuf, info.bytesconsumed);
442 a->pos += info.bytesconsumed;
443
444 // error which doesn't advance streambuf - end
445 } else {
446 endstream = true;
447 }
448
449 UNLOCK_S;
450
451 if (endstream) {
452 LOG_WARN("unable to decode further");
453 return DECODE_ERROR;
454 }
455
456 if (!info.samples) {
457 a->empty = true;
458 return DECODE_RUNNING;
459 }
460
461 frames = info.samples / info.channels;
462
463 if (a->skip) {
464 u32_t skip;
465 if (a->empty) {
466 a->empty = false;
467 a->skip -= frames;
468 LOG_DEBUG("gapless: first frame empty, skipped %u frames at start", frames);
469 }
470 skip = min(frames, a->skip);
471 LOG_DEBUG("gapless: skipping %u frames at start", skip);
472 frames -= skip;
473 a->skip -= skip;
474 iptr += skip * info.channels;
475 }
476
477 if (a->samples) {
478 if (a->samples < frames) {
479 LOG_DEBUG("gapless: trimming %u frames from end", frames - a->samples);
480 frames = (frames_t)a->samples;
481 }
482 a->samples -= frames;
483 }
484
485 LOG_SDEBUG("write %u frames", frames);
486
487 LOCK_O_direct;
488
489 while (frames > 0) {
490 frames_t f;
491 frames_t count;
492 s32_t *optr;
493
494 IF_DIRECT(
495 f = _buf_cont_write(outputbuf) / BYTES_PER_FRAME;
496 optr = (s32_t *)outputbuf->writep;
497 );
498 IF_PROCESS(
499 f = process.max_in_frames;
500 optr = (s32_t *)process.inbuf;
501 );
502
503 f = min(f, frames);
504 count = f;
505
506 if (info.channels == 2) {
507 while (count--) {
508 *optr++ = *iptr++ << 8;
509 *optr++ = *iptr++ << 8;
510 }
511 } else if (info.channels == 1) {
512 while (count--) {
513 *optr++ = *iptr << 8;
514 *optr++ = *iptr++ << 8;
515 }
516 } else {
517 LOG_WARN("unsupported number of channels");
518 }
519
520 frames -= f;
521
522 IF_DIRECT(
523 _buf_inc_writep(outputbuf, f * BYTES_PER_FRAME);
524 );
525 IF_PROCESS(
526 process.in_frames = f;
527 if (frames) LOG_ERROR("unhandled case");
528 );
529 }
530
531 UNLOCK_O_direct;
532
533 return DECODE_RUNNING;
534 }
535
536 static void faad_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
537 NeAACDecConfigurationPtr conf;
538
539 LOG_INFO("opening %s stream", size == '2' ? "adts" : "mp4");
540
541 a->type = size;
542 a->pos = a->consume = a->sample = a->nextchunk = 0;
543
544 if (a->chunkinfo) {
545 free(a->chunkinfo);
546 }
547 if (a->stsc) {
548 free(a->stsc);
549 }
550 a->chunkinfo = NULL;
551 a->stsc = NULL;
552 a->skip = 0;
553 a->samples = 0;
554 a->sttssamples = 0;
555 a->empty = false;
556
557 if (a->hAac) {
558 NEAAC(a, Close, a->hAac);
559 }
560 a->hAac = NEAAC(a, Open);
561
562 conf = NEAAC(a, GetCurrentConfiguration, a->hAac);
563
564 conf->outputFormat = FAAD_FMT_24BIT;
565 conf->downMatrix = 1;
566
567 if (!NEAAC(a, SetConfiguration, a->hAac, conf)) {
568 LOG_WARN("error setting config");
569 };
570 }
571
572 static void faad_close(void) {
573 NEAAC(a, Close, a->hAac);
574 a->hAac = NULL;
575 if (a->chunkinfo) {
576 free(a->chunkinfo);
577 a->chunkinfo = NULL;
578 }
579 if (a->stsc) {
580 free(a->stsc);
581 a->stsc = NULL;
582 }
583 }
584
585 static bool load_faad() {
586 #if !LINKALL
587 void *handle = dlopen(LIBFAAD, RTLD_NOW);
588 char *err;
589
590 if (!handle) {
591 LOG_INFO("dlerror: %s", dlerror());
592 return false;
593 }
594
595 a->NeAACDecGetCurrentConfiguration = dlsym(handle, "NeAACDecGetCurrentConfiguration");
596 a->NeAACDecSetConfiguration = dlsym(handle, "NeAACDecSetConfiguration");
597 a->NeAACDecOpen = dlsym(handle, "NeAACDecOpen");
598 a->NeAACDecClose = dlsym(handle, "NeAACDecClose");
599 a->NeAACDecInit = dlsym(handle, "NeAACDecInit");
600 a->NeAACDecInit2 = dlsym(handle, "NeAACDecInit2");
601 a->NeAACDecDecode = dlsym(handle, "NeAACDecDecode");
602 a->NeAACDecGetErrorMessage = dlsym(handle, "NeAACDecGetErrorMessage");
603
604 if ((err = dlerror()) != NULL) {
605 LOG_INFO("dlerror: %s", err);
606 return false;
607 }
608
609 LOG_INFO("loaded "LIBFAAD"");
610 #endif
611
612 return true;
613 }
614
615 struct codec *register_faad(void) {
616 static struct codec ret = {
617 'a', // id
618 "aac", // types
619 WRAPBUF_LEN, // min read
620 20480, // min space
621 faad_open, // open
622 faad_close, // close
623 faad_decode, // decode
624 };
625
626 a = malloc(sizeof(struct faad));
627 if (!a) {
628 return NULL;
629 }
630
631 a->hAac = NULL;
632 a->chunkinfo = NULL;
633 a->stsc = NULL;
634
635 if (!load_faad()) {
636 return NULL;
637 }
638
639 LOG_INFO("using faad to decode aac");
640 return &ret;
641 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 #if FFMPEG
23
24 #include <libavformat/avformat.h>
25 #include <libavcodec/avcodec.h>
26
27 #define READ_SIZE 4096 * 4 // this is large enough to ensure ffmpeg always gets new data when decode is called
28 #define WRITE_SIZE 256 * 1024 // FIXME - make smaller, but still to absorb max wma output
29
30 // FIXME - do we need to align these params as per ffmpeg on i386?
31 #define attribute_align_arg
32
33 struct ff_s {
34 // state for ffmpeg decoder
35 bool wma;
36 u8_t wma_mmsh;
37 u8_t wma_playstream;
38 u8_t wma_metadatastream;
39 u8_t *readbuf;
40 bool end_of_stream;
41 AVInputFormat *input_format;
42 AVFormatContext *formatC;
43 AVCodecContext *codecC;
44 AVFrame *frame;
45 AVPacket *avpkt;
46 unsigned mmsh_bytes_left;
47 unsigned mmsh_bytes_pad;
48 unsigned mmsh_packet_len;
49 #if !LINKALL
50 // ffmpeg symbols to be dynamically loaded from libavcodec
51 unsigned (* avcodec_version)(void);
52 AVCodec * (* avcodec_find_decoder)(int);
53 int attribute_align_arg (* avcodec_open2)(AVCodecContext *, const AVCodec *, AVDictionary **);
54 AVFrame * (* avcodec_alloc_frame)(void);
55 void (* avcodec_free_frame)(AVFrame **);
56 int attribute_align_arg (* avcodec_decode_audio4)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
57 // ffmpeg symbols to be dynamically loaded from libavformat
58 unsigned (* avformat_version)(void);
59 AVFormatContext * (* avformat_alloc_context)(void);
60 void (* avformat_free_context)(AVFormatContext *);
61 int (* avformat_open_input)(AVFormatContext **, const char *, AVInputFormat *, AVDictionary **);
62 int (* avformat_find_stream_info)(AVFormatContext *, AVDictionary **);
63 AVIOContext * (* avio_alloc_context)(unsigned char *, int, int, void *,
64 int (*read_packet)(void *, uint8_t *, int), int (*write_packet)(void *, uint8_t *, int), int64_t (*seek)(void *, int64_t, int));
65 void (* av_init_packet)(AVPacket *);
66 void (* av_free_packet)(AVPacket *);
67 int (* av_read_frame)(AVFormatContext *, AVPacket *);
68 AVInputFormat * (* av_find_input_format)(const char *);
69 void (* av_register_all)(void);
70 // ffmpeg symbols to be dynamically loaded from libavutil
71 unsigned (* avutil_version)(void);
72 void (* av_log_set_callback)(void (*)(void*, int, const char*, va_list));
73 void (* av_log_set_level)(int);
74 int (* av_strerror)(int, char *, size_t);
75 void * (* av_malloc)(size_t);
76 void (* av_freep)(void *);
77 #endif
78 };
79
80 static struct ff_s *ff;
81
82 extern log_level loglevel;
83
84 extern struct buffer *streambuf;
85 extern struct buffer *outputbuf;
86 extern struct streamstate stream;
87 extern struct outputstate output;
88 extern struct decodestate decode;
89 extern struct processstate process;
90
91 #define LOCK_S mutex_lock(streambuf->mutex)
92 #define UNLOCK_S mutex_unlock(streambuf->mutex)
93 #define LOCK_O mutex_lock(outputbuf->mutex)
94 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
95 #if PROCESS
96 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
97 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
98 #define IF_DIRECT(x) if (decode.direct) { x }
99 #define IF_PROCESS(x) if (!decode.direct) { x }
100 #else
101 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
102 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
103 #define IF_DIRECT(x) { x }
104 #define IF_PROCESS(x)
105 #endif
106
107 #if LINKALL
108 #define AV(h, fn, ...) (av_ ## fn)(__VA_ARGS__)
109 #define AVIO(h, fn, ...) (avio_ ## fn)(__VA_ARGS__)
110 #define AVCODEC(h, fn, ...) (avcodec_ ## fn)(__VA_ARGS__)
111 #define AVFORMAT(h, fn, ...) (avformat_ ## fn)(__VA_ARGS__)
112 #else
113 #define AV(h, fn, ...) (h)->av_##fn(__VA_ARGS__)
114 #define AVIO(h, fn, ...) (h)->avio_##fn(__VA_ARGS__)
115 #define AVCODEC(h, fn, ...) (h)->avcodec_##fn(__VA_ARGS__)
116 #define AVFORMAT(h, fn, ...) (h)->avformat_##fn(__VA_ARGS__)
117 #endif
118
119
120 // our own version of useful error function not included in earlier ffmpeg versions
121 static char *av__err2str(errnum) {
122 static char buf[64];
123 AV(ff, strerror, errnum, buf, 64);
124 return buf;
125 }
126
127 // parser to extract asf data packet length from asf header
128 const u8_t header_guid[16] = { 0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C };
129 const u8_t file_props_guid[16] = { 0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 };
130
131 static int _parse_packlen(void) {
132 int bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
133 u8_t *ptr = streambuf->readp;
134 int remain = 1;
135
136 while (bytes >= 24 && remain > 0) {
137 u32_t len = *(ptr+16) | *(ptr+17) << 8 | *(ptr+18) << 16 | *(ptr+19) << 24; // assume msb 32 bits are 0
138 if (!memcmp(ptr, header_guid, 16) && bytes >= 30) {
139 ptr += 30;
140 bytes -= 30;
141 remain = len - 30;
142 continue;
143 }
144 if (!memcmp(ptr, file_props_guid, 16) && len == 104) {
145 u32_t packlen = *(ptr+92) | *(ptr+93) << 8 | *(ptr+94) << 16 | *(ptr+95) << 24;
146 LOG_INFO("asf packet len: %u", packlen);
147 return packlen;
148 }
149 ptr += len;
150 bytes -= len;
151 remain -= len;
152 }
153
154 LOG_WARN("could not parse packet length");
155 return 0;
156 }
157
158 static int _read_data(void *opaque, u8_t *buffer, int buf_size) {
159 size_t bytes;
160
161 LOCK_S;
162
163 bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
164 ff->end_of_stream = (stream.state <= DISCONNECT && bytes == 0);
165 bytes = min(bytes, buf_size);
166
167 // for chunked wma extract asf header and data frames from framing structure
168 // pad asf data frames to size of packet extracted from asf header
169 if (ff->wma_mmsh) {
170 unsigned chunk_type = 0, chunk_len = 0;
171
172 if (ff->mmsh_bytes_left) {
173 // bytes remaining from previous frame
174 if (bytes >= ff->mmsh_bytes_left) {
175 bytes = ff->mmsh_bytes_left;
176 ff->mmsh_bytes_left = 0;
177 } else {
178 ff->mmsh_bytes_left -= bytes;
179 }
180 } else if (ff->mmsh_bytes_pad) {
181 // add padding for previous frame
182 bytes = min(ff->mmsh_bytes_pad, buf_size);
183 memset(buffer, 0, bytes);
184 ff->mmsh_bytes_pad -= bytes;
185 UNLOCK_S;
186 return bytes;
187 } else if (bytes >= 12) {
188 // new chunk header
189 chunk_type = (*(streambuf->readp) & 0x7f) | *(streambuf->readp + 1) << 8;
190 chunk_len = *(streambuf->readp + 2) | *(streambuf->readp + 3) << 8;
191 _buf_inc_readp(streambuf, 12);
192 bytes -= 12;
193 } else if (_buf_used(streambuf) >= 12) {
194 // new chunk header split over end of streambuf, read in two
195 u8_t header[12];
196 memcpy(header, streambuf->readp, bytes);
197 _buf_inc_readp(streambuf, bytes);
198 memcpy(header + bytes, streambuf->readp, 12 - bytes);
199 _buf_inc_readp(streambuf, 12 - bytes);
200 chunk_type = (header[0] & 0x7f) | header[1] << 8;
201 chunk_len = header[2] | header[3] << 8;
202 bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
203 bytes = min(bytes, buf_size);
204 } else {
205 // should not get here...
206 LOG_ERROR("chunk parser stalled bytes: %u %u", bytes, _buf_used(streambuf));
207 UNLOCK_S;
208 return 0;
209 }
210
211 if (chunk_type && chunk_len) {
212 if (chunk_type == 0x4824) {
213 // asf header - parse packet length
214 ff->mmsh_packet_len = _parse_packlen();
215 ff->mmsh_bytes_pad = 0;
216 } else if (chunk_type == 0x4424 && ff->mmsh_packet_len) {
217 // asf data packet - add padding
218 ff->mmsh_bytes_pad = ff->mmsh_packet_len - chunk_len + 8;
219 } else {
220 LOG_INFO("unknown chunk: %04x", chunk_type);
221 // other packet - no padding
222 ff->mmsh_bytes_pad = 0;
223 }
224
225 if (chunk_len - 8 <= bytes) {
226 bytes = chunk_len - 8;
227 ff->mmsh_bytes_left = 0;
228 } else {
229 ff->mmsh_bytes_left = chunk_len - 8 - bytes;
230 }
231 }
232
233 }
234
235 memcpy(buffer, streambuf->readp, bytes);
236
237 _buf_inc_readp(streambuf, bytes);
238
239 if (ff->mmsh_bytes_pad && bytes + ff->mmsh_bytes_pad < buf_size) {
240 memset(buffer + bytes, 0, ff->mmsh_bytes_pad);
241 bytes += ff->mmsh_bytes_pad;
242 ff->mmsh_bytes_pad = 0;
243 }
244
245 UNLOCK_S;
246
247 return bytes;
248 }
249
250 static decode_state ff_decode(void) {
251 int r, len, got_frame;
252 AVPacket pkt_c;
253 s32_t *optr = NULL;
254
255 if (decode.new_stream) {
256
257 AVIOContext *avio;
258 AVStream *av_stream;
259 AVCodec *codec;
260 int o;
261 int audio_stream = -1;
262
263 ff->mmsh_bytes_left = ff->mmsh_bytes_pad = ff->mmsh_packet_len = 0;
264
265 if (!ff->readbuf) {
266 ff->readbuf = AV(ff, malloc, READ_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
267 }
268
269 avio = AVIO(ff, alloc_context, ff->readbuf, READ_SIZE, 0, NULL, _read_data, NULL, NULL);
270 avio->seekable = 0;
271
272 ff->formatC = AVFORMAT(ff, alloc_context);
273 if (ff->formatC == NULL) {
274 LOG_ERROR("null context");
275 return DECODE_ERROR;
276 }
277
278 ff->formatC->pb = avio;
279 ff->formatC->flags |= AVFMT_FLAG_CUSTOM_IO | AVFMT_FLAG_NOPARSE;
280
281 o = AVFORMAT(ff, open_input, &ff->formatC, "", ff->input_format, NULL);
282 if (o < 0) {
283 LOG_WARN("avformat_open_input: %d %s", o, av__err2str(o));
284 return DECODE_ERROR;
285 }
286
287 LOG_INFO("format: name:%s lname:%s", ff->formatC->iformat->name, ff->formatC->iformat->long_name);
288
289 o = AVFORMAT(ff, find_stream_info, ff->formatC, NULL);
290 if (o < 0) {
291 LOG_WARN("avformat_find_stream_info: %d %s", o, av__err2str(o));
292 return DECODE_ERROR;
293 }
294
295 if (ff->wma && ff->wma_playstream < ff->formatC->nb_streams) {
296 if (ff->formatC->streams[ff->wma_playstream]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
297 LOG_INFO("using wma stream sent from server: %i", ff->wma_playstream);
298 audio_stream = ff->wma_playstream;
299 }
300 }
301
302 if (audio_stream == -1) {
303 int i;
304 for (i = 0; i < ff->formatC->nb_streams; ++i) {
305 if (ff->formatC->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
306 audio_stream = i;
307 LOG_INFO("found stream: %i", i);
308 break;
309 }
310 }
311 }
312
313 if (audio_stream == -1) {
314 LOG_WARN("no audio stream found");
315 return DECODE_ERROR;
316 }
317
318 av_stream = ff->formatC->streams[audio_stream];
319
320 ff->codecC = av_stream->codec;
321
322 codec = AVCODEC(ff, find_decoder, ff->codecC->codec_id);
323
324 AVCODEC(ff, open2, ff->codecC, codec, NULL);
325
326 ff->frame = AVCODEC(ff, alloc_frame);
327
328 ff->avpkt = AV(ff, malloc, sizeof(AVPacket));
329 if (ff->avpkt == NULL) {
330 LOG_ERROR("can't allocate avpkt");
331 return DECODE_ERROR;
332 }
333
334 AV(ff, init_packet, ff->avpkt);
335 ff->avpkt->data = NULL;
336 ff->avpkt->size = 0;
337
338 LOCK_O;
339 LOG_INFO("setting track_start");
340 output.next_sample_rate = decode_newstream(ff->codecC->sample_rate, output.supported_rates);
341 IF_DSD( output.next_dop = false; )
342 output.track_start = outputbuf->writep;
343 if (output.fade_mode) _checkfade(true);
344 decode.new_stream = false;
345 UNLOCK_O;
346 }
347
348 got_frame = 0;
349
350 if ((r = AV(ff, read_frame, ff->formatC, ff->avpkt)) < 0) {
351 if (r == AVERROR_EOF) {
352 if (ff->end_of_stream) {
353 LOG_INFO("decode complete");
354 return DECODE_COMPLETE;
355 } else {
356 LOG_INFO("codec end of file");
357 }
358 } else {
359 LOG_ERROR("av_read_frame error: %i %s", r, av__err2str(r));
360 }
361 return DECODE_RUNNING;
362 }
363
364 // clone packet as we are adjusting it
365 pkt_c = *ff->avpkt;
366
367 IF_PROCESS(
368 optr = (s32_t *)process.inbuf;
369 process.in_frames = 0;
370 );
371
372 while (pkt_c.size > 0 || got_frame) {
373
374 len = AVCODEC(ff, decode_audio4, ff->codecC, ff->frame, &got_frame, &pkt_c);
375 if (len < 0) {
376 LOG_ERROR("avcodec_decode_audio4 error: %i %s", len, av__err2str(len));
377 return DECODE_RUNNING;
378 }
379
380 pkt_c.data += len;
381 pkt_c.size -= len;
382
383 if (got_frame) {
384
385 s16_t *iptr16 = (s16_t *)ff->frame->data[0];
386 s32_t *iptr32 = (s32_t *)ff->frame->data[0];
387 s16_t *iptr16l = (s16_t *)ff->frame->data[0];
388 s16_t *iptr16r = (s16_t *)ff->frame->data[1];
389 s32_t *iptr32l = (s32_t *)ff->frame->data[0];
390 s32_t *iptr32r = (s32_t *)ff->frame->data[1];
391 float *iptrfl = (float *)ff->frame->data[0];
392 float *iptrfr = (float *)ff->frame->data[1];
393
394 frames_t frames = ff->frame->nb_samples;
395
396 LOG_SDEBUG("got audio channels: %u samples: %u format: %u", ff->codecC->channels, ff->frame->nb_samples,
397 ff->codecC->sample_fmt);
398
399 LOCK_O_direct;
400
401 while (frames > 0) {
402 frames_t count;
403 frames_t f;
404
405 IF_DIRECT(
406 optr = (s32_t *)outputbuf->writep;
407 f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
408 f = min(f, frames);
409 );
410
411 IF_PROCESS(
412 if (process.in_frames + frames > process.max_in_frames) {
413 LOG_WARN("exceeded process buffer size - dropping frames");
414 break;
415 }
416 f = frames;
417 );
418
419 count = f;
420
421 if (ff->codecC->channels == 2) {
422 if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S16) {
423 while (count--) {
424 *optr++ = *iptr16++ << 16;
425 *optr++ = *iptr16++ << 16;
426 }
427 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S32) {
428 while (count--) {
429 *optr++ = *iptr32++;
430 *optr++ = *iptr32++;
431 }
432 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S16P) {
433 while (count--) {
434 *optr++ = *iptr16l++ << 16;
435 *optr++ = *iptr16r++ << 16;
436 }
437 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S32P) {
438 while (count--) {
439 *optr++ = *iptr32l++;
440 *optr++ = *iptr32r++;
441 }
442 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_FLTP) {
443 while (count--) {
444 double scaledl = *iptrfl++ * 0x7fffffff;
445 double scaledr = *iptrfr++ * 0x7fffffff;
446 if (scaledl > 2147483647.0) scaledl = 2147483647.0;
447 if (scaledl < -2147483648.0) scaledl = -2147483648.0;
448 if (scaledr > 2147483647.0) scaledr = 2147483647.0;
449 if (scaledr < -2147483648.0) scaledr = -2147483648.0;
450 *optr++ = (s32_t)scaledl;
451 *optr++ = (s32_t)scaledr;
452 }
453 } else {
454 LOG_WARN("unsupported sample format: %u", ff->codecC->sample_fmt);
455 }
456 } else if (ff->codecC->channels == 1) {
457 if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S16) {
458 while (count--) {
459 *optr++ = *iptr16 << 16;
460 *optr++ = *iptr16++ << 16;
461 }
462 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S32) {
463 while (count--) {
464 *optr++ = *iptr32;
465 *optr++ = *iptr32++;
466 }
467 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S16P) {
468 while (count--) {
469 *optr++ = *iptr16l << 16;
470 *optr++ = *iptr16l++ << 16;
471 }
472 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_S32P) {
473 while (count--) {
474 *optr++ = *iptr32l;
475 *optr++ = *iptr32l++;
476 }
477 } else if (ff->codecC->sample_fmt == AV_SAMPLE_FMT_FLTP) {
478 while (count--) {
479 double scaled = *iptrfl++ * 0x7fffffff;
480 if (scaled > 2147483647.0) scaled = 2147483647.0;
481 if (scaled < -2147483648.0) scaled = -2147483648.0;
482 *optr++ = (s32_t)scaled;
483 *optr++ = (s32_t)scaled;
484 }
485 } else {
486 LOG_WARN("unsupported sample format: %u", ff->codecC->sample_fmt);
487 }
488 } else {
489 LOG_WARN("unsupported number of channels");
490 }
491
492 frames -= f;
493
494 IF_DIRECT(
495 _buf_inc_writep(outputbuf, f * BYTES_PER_FRAME);
496 );
497
498 IF_PROCESS(
499 process.in_frames += f;
500 );
501 }
502
503 UNLOCK_O_direct;
504 }
505 }
506
507 AV(ff, free_packet, ff->avpkt);
508
509 return DECODE_RUNNING;
510 }
511
512 static void _free_ff_data(void) {
513 if (ff->formatC) {
514 if (ff->formatC->pb) AV(ff, freep, &ff->formatC->pb);
515 AVFORMAT(ff, free_context, ff->formatC);
516 ff->formatC = NULL;
517 }
518
519 if (ff->frame) {
520 // ffmpeg version dependant free function
521 #if !LINKALL
522 ff->avcodec_free_frame ? AVCODEC(ff, free_frame, &ff->frame) : AV(ff, freep, &ff->frame);
523 #elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54,28,0)
524 AVCODEC(ff, free_frame, &ff->frame);
525 #else
526 AV(ff, freep, &ff->frame);
527 #endif
528 ff->frame = NULL;
529 }
530
531 if (ff->avpkt) {
532 AV(ff, free_packet, ff->avpkt);
533 AV(ff, freep, &ff->avpkt);
534 ff->avpkt = NULL;
535 }
536 }
537
538 static void ff_open_wma(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
539 _free_ff_data();
540
541 ff->input_format = AV(ff, find_input_format, "asf");
542 if (ff->input_format == NULL) {
543 LOG_ERROR("asf format not supported by ffmpeg library");
544 }
545
546 ff->wma = true;
547 ff->wma_mmsh = size - '0';
548 ff->wma_playstream = rate - 1;
549 ff->wma_metadatastream = chan != '?' ? chan : 0;
550
551 LOG_INFO("open wma chunking: %u playstream: %u metadatastream: %u", ff->wma_mmsh, ff->wma_playstream, ff->wma_metadatastream);
552 }
553
554 static void ff_open_alac(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
555 _free_ff_data();
556
557 ff->input_format = AV(ff, find_input_format, "mp4");
558 if (ff->input_format == NULL) {
559 LOG_ERROR("mp4 format not supported by ffmpeg library");
560 }
561
562 ff->wma = false;
563 ff->wma_mmsh = 0;
564
565 LOG_INFO("open alac");
566 }
567
568 static void ff_close(void) {
569 _free_ff_data();
570
571 if (ff->readbuf) {
572 AV(ff, freep, &ff->readbuf);
573 ff->readbuf = NULL;
574 }
575 }
576
577 static bool load_ff() {
578 #if !LINKALL
579 void *handle_codec = NULL, *handle_format = NULL, *handle_util = NULL;
580 char name[30];
581 char *err;
582
583 // we try to load the ffmpeg library version which matches the header file we are compiled with as structs differ between versions
584
585 sprintf(name, LIBAVCODEC, LIBAVCODEC_VERSION_MAJOR);
586 handle_codec = dlopen(name, RTLD_NOW);
587 if (!handle_codec) {
588 LOG_INFO("dlerror: %s", dlerror());
589 return false;
590 }
591
592 sprintf(name, LIBAVFORMAT, LIBAVFORMAT_VERSION_MAJOR);
593 handle_format = dlopen(name, RTLD_NOW);
594 if (!handle_format) {
595 LOG_INFO("dlerror: %s", dlerror());
596 return false;
597 }
598
599 sprintf(name, LIBAVUTIL, LIBAVUTIL_VERSION_MAJOR);
600 handle_util = dlopen(name, RTLD_NOW);
601 if (!handle_util) {
602 LOG_INFO("dlerror: %s", dlerror());
603 return false;
604 }
605
606 ff->avcodec_version = dlsym(handle_codec, "avcodec_version");
607 ff->avcodec_find_decoder = dlsym(handle_codec, "avcodec_find_decoder");
608 ff->avcodec_open2 = dlsym(handle_codec, "avcodec_open2");
609 ff->avcodec_alloc_frame = dlsym(handle_codec, "avcodec_alloc_frame");
610 ff->avcodec_free_frame = dlsym(handle_codec, "avcodec_free_frame");
611 ff->avcodec_decode_audio4 = dlsym(handle_codec, "avcodec_decode_audio4");
612 ff->av_init_packet = dlsym(handle_codec, "av_init_packet");
613 ff->av_free_packet = dlsym(handle_codec, "av_free_packet");
614
615 if ((err = dlerror()) != NULL) {
616 LOG_INFO("dlerror: %s", err);
617 return false;
618 }
619
620 LOG_INFO("loaded "LIBAVCODEC" (%u.%u.%u)", LIBAVCODEC_VERSION_MAJOR, ff->avcodec_version() >> 16, (ff->avcodec_version() >> 8) & 0xff, ff->avcodec_version() & 0xff);
621
622 ff->avformat_version = dlsym(handle_format, "avformat_version");
623 ff->avformat_alloc_context = dlsym(handle_format, "avformat_alloc_context");
624 ff->avformat_free_context = dlsym(handle_format, "avformat_free_context");
625 ff->avformat_open_input = dlsym(handle_format, "avformat_open_input");
626 ff->avformat_find_stream_info = dlsym(handle_format, "avformat_find_stream_info");
627 ff->avio_alloc_context = dlsym(handle_format, "avio_alloc_context");
628 ff->av_read_frame = dlsym(handle_format, "av_read_frame");
629 ff->av_find_input_format= dlsym(handle_format, "av_find_input_format");
630 ff->av_register_all = dlsym(handle_format, "av_register_all");
631
632 if ((err = dlerror()) != NULL) {
633 LOG_INFO("dlerror: %s", err);
634 return false;
635 }
636
637 LOG_INFO("loaded "LIBAVFORMAT" (%u.%u.%u)", LIBAVFORMAT_VERSION_MAJOR, ff->avformat_version() >> 16, (ff->avformat_version() >> 8) & 0xff, ff->avformat_version() & 0xff);
638
639 ff->avutil_version = dlsym(handle_util, "avutil_version");
640 ff->av_log_set_callback = dlsym(handle_util, "av_log_set_callback");
641 ff->av_log_set_level = dlsym(handle_util, "av_log_set_level");
642 ff->av_strerror = dlsym(handle_util, "av_strerror");
643 ff->av_malloc = dlsym(handle_util, "av_malloc");
644 ff->av_freep = dlsym(handle_util, "av_freep");
645
646 if ((err = dlerror()) != NULL) {
647 LOG_INFO("dlerror: %s", err);
648 return false;
649 }
650
651 LOG_INFO("loaded "LIBAVUTIL" (%u.%u.%u)", LIBAVUTIL_VERSION_MAJOR, ff->avutil_version() >> 16, (ff->avutil_version() >> 8) & 0xff, ff->avutil_version() & 0xff);
652
653 #endif
654
655 return true;
656 }
657
658 static int ff_log_level = 0;
659
660 void av_err_callback(void *avcl, int level, const char *fmt, va_list vl) {
661 if (level > ff_log_level) return;
662 fprintf(stderr, "%s ffmpeg: ", logtime());
663 vfprintf(stderr, fmt, vl);
664 fflush(stderr);
665 }
666
667 static bool registered = false;
668
669 struct codec *register_ff(const char *codec) {
670 if (!registered) {
671
672 ff = malloc(sizeof(struct ff_s));
673 if (!ff) {
674 return NULL;
675 }
676
677 memset(ff, 0, sizeof(struct ff_s));
678
679 if (!load_ff()) {
680 return NULL;
681 }
682
683 switch (loglevel) {
684 case lERROR:
685 ff_log_level = AV_LOG_ERROR; break;
686 case lWARN:
687 ff_log_level = AV_LOG_WARNING; break;
688 case lINFO:
689 ff_log_level = AV_LOG_INFO; break;
690 case lDEBUG:
691 ff_log_level = AV_LOG_VERBOSE; break;
692 default: break;
693 }
694
695 AV(ff, log_set_callback, av_err_callback);
696
697 AV(ff, register_all);
698
699 registered = true;
700 }
701
702 if (!strcmp(codec, "wma")) {
703
704 static struct codec ret = {
705 'w', // id
706 "wma,wmap,wmal", // types
707 READ_SIZE, // min read
708 WRITE_SIZE, // min space
709 ff_open_wma, // open
710 ff_close, // close
711 ff_decode, // decode
712 };
713
714 LOG_INFO("using ffmpeg to decode wma,wmap,wmal");
715 return &ret;
716 }
717
718 if (!strcmp(codec, "alc")) {
719
720 static struct codec ret = {
721 'l', // id
722 "alc", // types
723 READ_SIZE, // min read
724 WRITE_SIZE, // min space
725 ff_open_alac,// open
726 ff_close, // close
727 ff_decode, // decode
728 };
729
730 LOG_INFO("using ffmpeg to decode alc");
731 return &ret;
732 }
733
734 return NULL;
735 }
736
737 #endif
0 /*
1 * Squeezelite - lightweight headless squeezeplay emulator for linux
2 *
3 * (c) Adrian Smith 2012, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 #include <FLAC/stream_decoder.h>
23
24 struct flac {
25 FLAC__StreamDecoder *decoder;
26 #if !LINKALL
27 // FLAC symbols to be dynamically loaded
28 const char **FLAC__StreamDecoderErrorStatusString;
29 const char **FLAC__StreamDecoderStateString;
30 FLAC__StreamDecoder * (* FLAC__stream_decoder_new)(void);
31 FLAC__bool (* FLAC__stream_decoder_reset)(FLAC__StreamDecoder *decoder);
32 void (* FLAC__stream_decoder_delete)(FLAC__StreamDecoder *decoder);
33 FLAC__StreamDecoderInitStatus (* FLAC__stream_decoder_init_stream)(
34 FLAC__StreamDecoder *decoder,
35 FLAC__StreamDecoderReadCallback read_callback,
36 FLAC__StreamDecoderSeekCallback seek_callback,
37 FLAC__StreamDecoderTellCallback tell_callback,
38 FLAC__StreamDecoderLengthCallback length_callback,
39 FLAC__StreamDecoderEofCallback eof_callback,
40 FLAC__StreamDecoderWriteCallback write_callback,
41 FLAC__StreamDecoderMetadataCallback metadata_callback,
42 FLAC__StreamDecoderErrorCallback error_callback,
43 void *client_data
44 );
45 FLAC__bool (* FLAC__stream_decoder_process_single)(FLAC__StreamDecoder *decoder);
46 FLAC__StreamDecoderState (* FLAC__stream_decoder_get_state)(const FLAC__StreamDecoder *decoder);
47 #endif
48 };
49
50 static struct flac *f;
51
52 extern log_level loglevel;
53
54 extern struct buffer *streambuf;
55 extern struct buffer *outputbuf;
56 extern struct streamstate stream;
57 extern struct outputstate output;
58 extern struct decodestate decode;
59 extern struct processstate process;
60
61 #define LOCK_S mutex_lock(streambuf->mutex)
62 #define UNLOCK_S mutex_unlock(streambuf->mutex)
63 #define LOCK_O mutex_lock(outputbuf->mutex)
64 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
65 #if PROCESS
66 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
67 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
68 #define IF_DIRECT(x) if (decode.direct) { x }
69 #define IF_PROCESS(x) if (!decode.direct) { x }
70 #else
71 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
72 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
73 #define IF_DIRECT(x) { x }
74 #define IF_PROCESS(x)
75 #endif
76
77 #if LINKALL
78 #define FLAC(h, fn, ...) (FLAC__ ## fn)(__VA_ARGS__)
79 #define FLAC_A(h, a) (FLAC__ ## a)
80 #else
81 #define FLAC(h, fn, ...) (h)->FLAC__##fn(__VA_ARGS__)
82 #define FLAC_A(h, a) (h)->FLAC__ ## a
83 #endif
84
85 static FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *want, void *client_data) {
86 size_t bytes;
87 bool end;
88
89 LOCK_S;
90 bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
91 bytes = min(bytes, *want);
92 end = (stream.state <= DISCONNECT && bytes == 0);
93
94 memcpy(buffer, streambuf->readp, bytes);
95 _buf_inc_readp(streambuf, bytes);
96 UNLOCK_S;
97
98 *want = bytes;
99
100 return end ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
101 }
102
103 static FLAC__StreamDecoderWriteStatus write_cb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
104 const FLAC__int32 *const buffer[], void *client_data) {
105
106 size_t frames = frame->header.blocksize;
107 unsigned bits_per_sample = frame->header.bits_per_sample;
108 unsigned channels = frame->header.channels;
109
110 FLAC__int32 *lptr = (FLAC__int32 *)buffer[0];
111 FLAC__int32 *rptr = (FLAC__int32 *)buffer[channels > 1 ? 1 : 0];
112
113 if (decode.new_stream) {
114 LOCK_O;
115 LOG_INFO("setting track_start");
116 output.track_start = outputbuf->writep;
117 decode.new_stream = false;
118
119 #if DSD
120 if (output.has_dop && bits_per_sample == 24 && is_flac_dop((u32_t *)lptr, (u32_t *)rptr, frames)) {
121 LOG_INFO("file contains DOP");
122 output.next_dop = true;
123 output.next_sample_rate = frame->header.sample_rate;
124 output.fade = FADE_INACTIVE;
125 } else {
126 output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.supported_rates);
127 output.next_dop = false;
128 if (output.fade_mode) _checkfade(true);
129 }
130 #else
131 output.next_sample_rate = decode_newstream(frame->header.sample_rate, output.supported_rates);
132 if (output.fade_mode) _checkfade(true);
133 #endif
134
135 UNLOCK_O;
136 }
137
138 LOCK_O_direct;
139
140 while (frames > 0) {
141 frames_t f;
142 frames_t count;
143 s32_t *optr;
144
145 IF_DIRECT(
146 optr = (s32_t *)outputbuf->writep;
147 f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
148 );
149 IF_PROCESS(
150 optr = (s32_t *)process.inbuf;
151 f = process.max_in_frames;
152 );
153
154 f = min(f, frames);
155
156 count = f;
157
158 if (bits_per_sample == 8) {
159 while (count--) {
160 *optr++ = *lptr++ << 24;
161 *optr++ = *rptr++ << 24;
162 }
163 } else if (bits_per_sample == 16) {
164 while (count--) {
165 *optr++ = *lptr++ << 16;
166 *optr++ = *rptr++ << 16;
167 }
168 } else if (bits_per_sample == 24) {
169 while (count--) {
170 *optr++ = *lptr++ << 8;
171 *optr++ = *rptr++ << 8;
172 }
173 } else if (bits_per_sample == 32) {
174 while (count--) {
175 *optr++ = *lptr++;
176 *optr++ = *rptr++;
177 }
178 } else {
179 LOG_ERROR("unsupported bits per sample: %u", bits_per_sample);
180 }
181
182 frames -= f;
183
184 IF_DIRECT(
185 _buf_inc_writep(outputbuf, f * BYTES_PER_FRAME);
186 );
187 IF_PROCESS(
188 process.in_frames = f;
189 if (frames) LOG_ERROR("unhandled case");
190 );
191 }
192
193 UNLOCK_O_direct;
194
195 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
196 }
197
198 static void error_cb(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
199 LOG_INFO("flac error: %s", FLAC_A(f, StreamDecoderErrorStatusString)[status]);
200 }
201
202 static void flac_open(u8_t sample_size, u8_t sample_rate, u8_t channels, u8_t endianness) {
203 if (f->decoder) {
204 FLAC(f, stream_decoder_reset, f->decoder);
205 } else {
206 f->decoder = FLAC(f, stream_decoder_new);
207 }
208 FLAC(f, stream_decoder_init_stream, f->decoder, &read_cb, NULL, NULL, NULL, NULL, &write_cb, NULL, &error_cb, NULL);
209 }
210
211 static void flac_close(void) {
212 FLAC(f, stream_decoder_delete, f->decoder);
213 f->decoder = NULL;
214 }
215
216 static decode_state flac_decode(void) {
217 bool ok = FLAC(f, stream_decoder_process_single, f->decoder);
218 FLAC__StreamDecoderState state = FLAC(f, stream_decoder_get_state, f->decoder);
219
220 if (!ok && state != FLAC__STREAM_DECODER_END_OF_STREAM) {
221 LOG_INFO("flac error: %s", FLAC_A(f, StreamDecoderStateString)[state]);
222 };
223
224 if (state == FLAC__STREAM_DECODER_END_OF_STREAM) {
225 return DECODE_COMPLETE;
226 } else if (state > FLAC__STREAM_DECODER_END_OF_STREAM) {
227 return DECODE_ERROR;
228 } else {
229 return DECODE_RUNNING;
230 }
231 }
232
233 static bool load_flac() {
234 #if !LINKALL
235 void *handle = dlopen(LIBFLAC, RTLD_NOW);
236 char *err;
237
238 if (!handle) {
239 LOG_INFO("dlerror: %s", dlerror());
240 return false;
241 }
242
243 f->FLAC__StreamDecoderErrorStatusString = dlsym(handle, "FLAC__StreamDecoderErrorStatusString");
244 f->FLAC__StreamDecoderStateString = dlsym(handle, "FLAC__StreamDecoderStateString");
245 f->FLAC__stream_decoder_new = dlsym(handle, "FLAC__stream_decoder_new");
246 f->FLAC__stream_decoder_reset = dlsym(handle, "FLAC__stream_decoder_reset");
247 f->FLAC__stream_decoder_delete = dlsym(handle, "FLAC__stream_decoder_delete");
248 f->FLAC__stream_decoder_init_stream = dlsym(handle, "FLAC__stream_decoder_init_stream");
249 f->FLAC__stream_decoder_process_single = dlsym(handle, "FLAC__stream_decoder_process_single");
250 f->FLAC__stream_decoder_get_state = dlsym(handle, "FLAC__stream_decoder_get_state");
251
252 if ((err = dlerror()) != NULL) {
253 LOG_INFO("dlerror: %s", err);
254 return false;
255 }
256
257 LOG_INFO("loaded "LIBFLAC);
258 #endif
259
260 return true;
261 }
262
263 struct codec *register_flac(void) {
264 static struct codec ret = {
265 'f', // id
266 "flc", // types
267 8192, // min read
268 102400, // min space
269 flac_open, // open
270 flac_close, // close
271 flac_decode, // decode
272 };
273
274 f = malloc(sizeof(struct flac));
275 if (!f) {
276 return NULL;
277 }
278
279 f->decoder = NULL;
280
281 if (!load_flac()) {
282 return NULL;
283 }
284
285 LOG_INFO("using flac to decode flc");
286 return &ret;
287 }
+248
-0
ir.c less more
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // ir thread - linux only
21
22 #include "squeezelite.h"
23
24 #if IR
25
26 #include <lirc/lirc_client.h>
27
28 #define LIRC_CLIENT_ID "squeezelite"
29
30 static log_level loglevel;
31
32 struct irstate ir;
33
34 static struct lirc_config *config = NULL;
35 static sockfd fd = -1;
36
37 static thread_type thread;
38
39 #define LOCK_I mutex_lock(ir.mutex)
40 #define UNLOCK_I mutex_unlock(ir.mutex)
41
42 #if !LINKALL
43 struct lirc {
44 // LIRC symbols to be dynamically loaded
45 int (* lirc_init)(char *prog, int verbose);
46 int (* lirc_deinit)(void);
47 int (* lirc_readconfig)(char *file, struct lirc_config **config, int (check) (char *s));
48 void (* lirc_freeconfig)(struct lirc_config *config);
49 int (* lirc_nextcode)(char **code);
50 int (* lirc_code2char)(struct lirc_config *config, char *code, char **string);
51 };
52
53 static struct lirc *i;
54 #endif
55
56 #if LINKALL
57 #define LIRC(h, fn, ...) (lirc_ ## fn)(__VA_ARGS__)
58 #else
59 #define LIRC(h, fn, ...) (h)->lirc_##fn(__VA_ARGS__)
60 #endif
61
62 // cmds based on entires in Slim_Device_Remote.ir
63 // these may appear as config entries in .lircrc files
64 static struct {
65 char *cmd;
66 u32_t code;
67 } cmdmap[] = {
68 { "voldown", 0x768900ff },
69 { "volup", 0x7689807f },
70 { "rew", 0x7689c03f },
71 { "fwd", 0x7689a05f },
72 { "pause", 0x768920df },
73 { "play", 0x768910ef },
74 { "power", 0x768940bf },
75 { "muting", 0x7689c43b },
76 { "power_on", 0x76898f70 },
77 { "power_off",0x76898778 },
78 { NULL, 0 },
79 };
80
81 // selected lirc namespace button names as defaults - some support repeat
82 static struct {
83 char *lirc;
84 u32_t code;
85 bool repeat;
86 } keymap[] = {
87 { "KEY_VOLUMEDOWN", 0x768900ff, true },
88 { "KEY_VOLUMEUP", 0x7689807f, true },
89 { "KEY_PREVIOUS", 0x7689c03f, false },
90 { "KEY_REWIND", 0x7689c03f, false },
91 { "KEY_NEXT", 0x7689a05f, false },
92 { "KEY_FORWARD", 0x7689a05f, false },
93 { "KEY_PAUSE", 0x768920df, true },
94 { "KEY_PLAY", 0x768910ef, false },
95 { "KEY_POWER", 0x768940bf, false },
96 { "KEY_MUTE", 0x7689c43b, false },
97 { NULL, 0 , false },
98 };
99
100 static u32_t ir_cmd_map(const char *c) {
101 int i;
102 for (i = 0; cmdmap[i].cmd; i++) {
103 if (!strcmp(c, cmdmap[i].cmd)) {
104 return cmdmap[i].code;
105 }
106 }
107 return 0;
108 }
109
110 static u32_t ir_key_map(const char *c, const char *r) {
111 int i;
112 for (i = 0; keymap[i].lirc; i++) {
113 if (!strcmp(c, keymap[i].lirc)) {
114 if (keymap[i].repeat || !strcmp(r, "00")) {
115 return keymap[i].code;
116 }
117 LOG_DEBUG("repeat suppressed");
118 break;
119 }
120 }
121 return 0;
122 }
123
124 static void *ir_thread() {
125 char *code;
126
127 while (fd > 0 && LIRC(i, nextcode, &code) == 0) {
128
129 u32_t now = gettime_ms();
130 u32_t ir_code = 0;
131
132 if (code == NULL) continue;
133
134 if (config) {
135 // allow lirc_client to decode then lookup cmd in our table
136 // we can only send one IR event to slimproto so break after first one
137 char *c;
138 while (LIRC(i, code2char, config, code, &c) == 0 && c != NULL) {
139 ir_code = ir_cmd_map(c);
140 if (ir_code) {
141 LOG_DEBUG("ir cmd: %s -> %x", c, ir_code);
142 }
143 }
144 }
145
146 if (!ir_code) {
147 // try to match on lirc button name if it is from the standard namespace
148 // this allows use of non slim remotes without a specific entry in .lircrc
149 char *b, *r;
150 strtok(code, " \n"); // discard
151 r = strtok(NULL, " \n"); // repeat count
152 b = strtok(NULL, " \n"); // key name
153 if (r && b) {
154 ir_code = ir_key_map(b, r);
155 LOG_DEBUG("ir lirc: %s [%s] -> %x", b, r, ir_code);
156 }
157 }
158
159 if (ir_code) {
160 LOCK_I;
161 if (ir.code) {
162 LOG_DEBUG("code dropped");
163 }
164 ir.code = ir_code;
165 ir.ts = now;
166 UNLOCK_I;
167 wake_controller();
168 }
169
170 free(code);
171 }
172
173 return 0;
174 }
175
176 #if !LINKALL
177 static bool load_lirc() {
178 void *handle = dlopen(LIBLIRC, RTLD_NOW);
179 char *err;
180
181 if (!handle) {
182 LOG_INFO("dlerror: %s", dlerror());
183 return false;
184 }
185
186 i->lirc_init = dlsym(handle, "lirc_init");
187 i->lirc_deinit = dlsym(handle, "lirc_deinit");
188 i->lirc_readconfig = dlsym(handle, "lirc_readconfig");
189 i->lirc_freeconfig = dlsym(handle, "lirc_freeconfig");
190 i->lirc_nextcode = dlsym(handle, "lirc_nextcode");
191 i->lirc_code2char = dlsym(handle, "lirc_code2char");
192
193 if ((err = dlerror()) != NULL) {
194 LOG_INFO("dlerror: %s", err);
195 return false;
196 }
197
198 LOG_INFO("loaded "LIBLIRC);
199 return true;
200 }
201 #endif
202
203 void ir_init(log_level level, char *lircrc) {
204 loglevel = level;
205
206 #if !LINKALL
207 i = malloc(sizeof(struct lirc));
208 if (!i || !load_lirc()) {
209 return;
210 }
211 #endif
212
213 fd = LIRC(i, init, LIRC_CLIENT_ID, 0);
214
215 if (fd > 0) {
216 if (LIRC(i, readconfig,lircrc, &config, NULL) != 0) {
217 LOG_WARN("error reading config: %s", lircrc);
218 }
219
220 mutex_create(ir.mutex);
221
222 pthread_attr_t attr;
223 pthread_attr_init(&attr);
224 pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + IR_THREAD_STACK_SIZE);
225 pthread_create(&thread, &attr, ir_thread, NULL);
226 pthread_attr_destroy(&attr);
227
228 } else {
229 LOG_WARN("failed to connect to lircd - ir processing disabled");
230 }
231 }
232
233 void ir_close(void) {
234 if (fd > 0) {
235 fd = -1;
236 if (config) {
237 LIRC(i, freeconfig, config);
238 }
239 LIRC(i, deinit);
240
241 pthread_cancel(thread);
242 pthread_join(thread, NULL);
243 mutex_destroy(ir.mutex);
244 }
245 }
246
247 #endif //#if IR
+414
-0
mad.c less more
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 #include <mad.h>
23
24 #define MAD_DELAY 529
25
26 #define READBUF_SIZE 2048 // local buffer used by decoder: FIXME merge with any other decoders needing one?
27
28 struct mad {
29 u8_t *readbuf;
30 unsigned readbuf_len;
31 struct mad_stream stream;
32 struct mad_frame frame;
33 struct mad_synth synth;
34 enum mad_error last_error;
35 // for lame gapless processing
36 int checktags;
37 u32_t consume;
38 u32_t skip;
39 u64_t samples;
40 u32_t padding;
41 #if !LINKALL
42 // mad symbols to be dynamically loaded
43 void (* mad_stream_init)(struct mad_stream *);
44 void (* mad_frame_init)(struct mad_frame *);
45 void (* mad_synth_init)(struct mad_synth *);
46 void (* mad_frame_finish)(struct mad_frame *);
47 void (* mad_stream_finish)(struct mad_stream *);
48 void (* mad_stream_buffer)(struct mad_stream *, unsigned char const *, unsigned long);
49 int (* mad_frame_decode)(struct mad_frame *, struct mad_stream *);
50 void (* mad_synth_frame)(struct mad_synth *, struct mad_frame const *);
51 char const *(* mad_stream_errorstr)(struct mad_stream const *);
52 #endif
53 };
54
55 static struct mad *m;
56
57 extern log_level loglevel;
58
59 extern struct buffer *streambuf;
60 extern struct buffer *outputbuf;
61 extern struct streamstate stream;
62 extern struct outputstate output;
63 extern struct decodestate decode;
64 extern struct processstate process;
65
66 #define LOCK_S mutex_lock(streambuf->mutex)
67 #define UNLOCK_S mutex_unlock(streambuf->mutex)
68 #define LOCK_O mutex_lock(outputbuf->mutex)
69 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
70 #if PROCESS
71 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
72 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
73 #define IF_DIRECT(x) if (decode.direct) { x }
74 #define IF_PROCESS(x) if (!decode.direct) { x }
75 #else
76 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
77 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
78 #define IF_DIRECT(x) { x }
79 #define IF_PROCESS(x)
80 #endif
81
82 #if LINKALL
83 #define MAD(h, fn, ...) (mad_ ## fn)(__VA_ARGS__)
84 #else
85 #define MAD(h, fn, ...) (h)->mad_##fn(__VA_ARGS__)
86 #endif
87
88 // based on libmad minimad.c scale
89 static inline u32_t scale(mad_fixed_t sample) {
90 sample += (1L << (MAD_F_FRACBITS - 24));
91
92 if (sample >= MAD_F_ONE)
93 sample = MAD_F_ONE - 1;
94 else if (sample < -MAD_F_ONE)
95 sample = -MAD_F_ONE;
96
97 return (s32_t)(sample >> (MAD_F_FRACBITS + 1 - 24)) << 8;
98 }
99
100 // check for id3.2 tag at start of file - http://id3.org/id3v2.4.0-structure, return length
101 static unsigned _check_id3_tag(size_t bytes) {
102 u8_t *ptr = streambuf->readp;
103 u32_t size = 0;
104
105 if (bytes > 10 && *ptr == 'I' && *(ptr+1) == 'D' && *(ptr+2) == '3') {
106 // size is encoded as syncsafe integer, add 10 if footer present
107 if (*(ptr+6) < 0x80 && *(ptr+7) < 0x80 && *(ptr+8) < 0x80 && *(ptr+9) < 0x80) {
108 size = 10 + (*(ptr+6) << 21) + (*(ptr+7) << 14) + (*(ptr+8) << 7) + *(ptr+9) + ((*(ptr+5) & 0x10) ? 10 : 0);
109 LOG_DEBUG("id3.2 tag len: %u", size);
110 }
111 }
112
113 return size;
114 }
115
116 // check for lame gapless params, don't advance streambuf
117 static void _check_lame_header(size_t bytes) {
118 u8_t *ptr = streambuf->readp;
119
120 if (*ptr == 0xff && (*(ptr+1) & 0xf0) == 0xf0 && bytes > 180) {
121
122 u32_t frame_count = 0, enc_delay = 0, enc_padding = 0;
123 u8_t flags;
124
125 // 2 channels
126 if (!memcmp(ptr + 36, "Xing", 4) || !memcmp(ptr + 36, "Info", 4)) {
127 ptr += 36 + 7;
128 // mono
129 } else if (!memcmp(ptr + 21, "Xing", 4) || !memcmp(ptr + 21, "Info", 4)) {
130 ptr += 21 + 7;
131 }
132
133 flags = *ptr;
134
135 if (flags & 0x01) {
136 frame_count = unpackN((u32_t *)(ptr + 1));
137 ptr += 4;
138 }
139 if (flags & 0x02) ptr += 4;
140 if (flags & 0x04) ptr += 100;
141 if (flags & 0x08) ptr += 4;
142
143 if (!!memcmp(ptr+1, "LAME", 4)) {
144 return;
145 }
146
147 ptr += 22;
148
149 enc_delay = (*ptr << 4 | *(ptr + 1) >> 4) + MAD_DELAY;
150 enc_padding = (*(ptr + 1) & 0xF) << 8 | *(ptr + 2);
151 enc_padding = enc_padding > MAD_DELAY ? enc_padding - MAD_DELAY : 0;
152
153 // add one frame to initial skip for this (empty) frame
154 m->skip = enc_delay + 1152;
155 m->samples = frame_count * 1152 - enc_delay - enc_padding;
156 m->padding = enc_padding;
157
158 LOG_INFO("gapless: skip: %u samples: " FMT_u64 " delay: %u padding: %u", m->skip, m->samples, enc_delay, enc_padding);
159 }
160 }
161
162 static decode_state mad_decode(void) {
163 size_t bytes;
164 bool eos = false;
165
166 LOCK_S;
167 bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
168
169 if (m->checktags) {
170 if (m->checktags == 1) {
171 m->consume = _check_id3_tag(bytes);
172 m->checktags = 2;
173 }
174 if (m->consume) {
175 u32_t consume = min(m->consume, bytes);
176 LOG_DEBUG("consume: %u of %u", consume, m->consume);
177 _buf_inc_readp(streambuf, consume);
178 m->consume -= consume;
179 UNLOCK_S;
180 return DECODE_RUNNING;
181 }
182 if (m->checktags == 2) {
183 if (!stream.meta_interval) {
184 _check_lame_header(bytes);
185 }
186 m->checktags = 0;
187 }
188 }
189
190 if (m->stream.next_frame && m->readbuf_len) {
191 m->readbuf_len -= m->stream.next_frame - m->readbuf;
192 memmove(m->readbuf, m->stream.next_frame, m->readbuf_len);
193 }
194
195 bytes = min(bytes, READBUF_SIZE - m->readbuf_len);
196 memcpy(m->readbuf + m->readbuf_len, streambuf->readp, bytes);
197 m->readbuf_len += bytes;
198 _buf_inc_readp(streambuf, bytes);
199
200 if (stream.state <= DISCONNECT && _buf_used(streambuf) == 0) {
201 eos = true;
202 LOG_DEBUG("end of stream");
203 memset(m->readbuf + m->readbuf_len, 0, MAD_BUFFER_GUARD);
204 m->readbuf_len += MAD_BUFFER_GUARD;
205 }
206
207 UNLOCK_S;
208
209 MAD(m, stream_buffer, &m->stream, m->readbuf, m->readbuf_len);
210
211 while (true) {
212 size_t frames;
213 s32_t *iptrl;
214 s32_t *iptrr;
215 unsigned max_frames;
216
217 if (MAD(m, frame_decode, &m->frame, &m->stream) == -1) {
218 decode_state ret;
219 if (!eos && m->stream.error == MAD_ERROR_BUFLEN) {
220 ret = DECODE_RUNNING;
221 } else if (eos && (m->stream.error == MAD_ERROR_BUFLEN || m->stream.error == MAD_ERROR_LOSTSYNC)) {
222 ret = DECODE_COMPLETE;
223 } else if (!MAD_RECOVERABLE(m->stream.error)) {
224 LOG_INFO("mad_frame_decode error: %s - stopping decoder", MAD(m, stream_errorstr, &m->stream));
225 ret = DECODE_COMPLETE;
226 } else {
227 if (m->stream.error != m->last_error) {
228 // suppress repeat error messages
229 LOG_DEBUG("mad_frame_decode error: %s", MAD(m, stream_errorstr, &m->stream));
230 }
231 ret = DECODE_RUNNING;
232 }
233 m->last_error = m->stream.error;
234 return ret;
235 };
236
237 MAD(m, synth_frame, &m->synth, &m->frame);
238
239 if (decode.new_stream) {
240 LOCK_O;
241 LOG_INFO("setting track_start");
242 output.next_sample_rate = decode_newstream(m->synth.pcm.samplerate, output.supported_rates);
243 IF_DSD( output.next_dop = false; )
244 output.track_start = outputbuf->writep;
245 if (output.fade_mode) _checkfade(true);
246 decode.new_stream = false;
247 UNLOCK_O;
248 }
249
250 LOCK_O_direct;
251
252 IF_DIRECT(
253 max_frames = _buf_space(outputbuf) / BYTES_PER_FRAME;
254 );
255 IF_PROCESS(
256 max_frames = process.max_in_frames - process.in_frames;
257 );
258
259 if (m->synth.pcm.length > max_frames) {
260 LOG_WARN("too many samples - dropping samples");
261 m->synth.pcm.length = max_frames;
262 }
263
264 frames = m->synth.pcm.length;
265 iptrl = m->synth.pcm.samples[0];
266 iptrr = m->synth.pcm.samples[ m->synth.pcm.channels - 1 ];
267
268 if (m->skip) {
269 u32_t skip = min(m->skip, frames);
270 LOG_DEBUG("gapless: skipping %u frames at start", skip);
271 frames -= skip;
272 m->skip -= skip;
273 iptrl += skip;
274 iptrr += skip;
275 }
276
277 if (m->samples) {
278 if (m->samples < frames) {
279 LOG_DEBUG("gapless: trimming %u frames from end", frames - m->samples);
280 frames = (size_t)m->samples;
281 }
282 m->samples -= frames;
283 if (m->samples > 0 && eos && !(m->stream.next_frame[0] == 0xff && (m->stream.next_frame[1] & 0xf0) == 0xf0)) {
284 // this is the last frame to be decoded, but more samples expected so we must have skipped, remove padding
285 // note this only works if the padding is less than one frame of 1152 bytes otherswise some gap will remain
286 LOG_DEBUG("gapless: early end - trimming padding from end");
287 if (frames >= m->padding) {
288 frames -= m->padding;
289 } else {
290 frames = 0;
291 }
292 m->samples = 0;
293 }
294 }
295
296 LOG_SDEBUG("write %u frames", frames);
297
298 while (frames > 0) {
299 size_t f, count;
300 s32_t *optr;
301
302 IF_DIRECT(
303 f = min(frames, _buf_cont_write(outputbuf) / BYTES_PER_FRAME);
304 optr = (s32_t *)outputbuf->writep;
305 );
306 IF_PROCESS(
307 f = min(frames, process.max_in_frames - process.in_frames);
308 optr = (s32_t *)((u8_t *)process.inbuf + process.in_frames * BYTES_PER_FRAME);
309 );
310
311 count = f;
312
313 while (count--) {
314 *optr++ = scale(*iptrl++);
315 *optr++ = scale(*iptrr++);
316 }
317
318 frames -= f;
319
320 IF_DIRECT(
321 _buf_inc_writep(outputbuf, f * BYTES_PER_FRAME);
322 );
323 IF_PROCESS(
324 process.in_frames += f;
325 );
326 }
327
328 UNLOCK_O_direct;
329 }
330
331 return eos ? DECODE_COMPLETE : DECODE_RUNNING;
332 }
333
334 static void mad_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
335 if (!m->readbuf) {
336 m->readbuf = malloc(READBUF_SIZE + MAD_BUFFER_GUARD);
337 }
338 m->checktags = 1;
339 m->consume = 0;
340 m->skip = MAD_DELAY;
341 m->samples = 0;
342 m->readbuf_len = 0;
343 m->last_error = MAD_ERROR_NONE;
344 MAD(m, stream_init, &m->stream);
345 MAD(m, frame_init, &m->frame);
346 MAD(m, synth_init, &m->synth);
347 }
348
349 static void mad_close(void) {
350 mad_synth_finish(&m->synth); // macro only in current version
351 MAD(m, frame_finish, &m->frame);
352 MAD(m, stream_finish, &m->stream);
353 free(m->readbuf);
354 m->readbuf = NULL;
355 }
356
357 static bool load_mad() {
358 #if !LINKALL
359 void *handle = dlopen(LIBMAD, RTLD_NOW);
360 char *err;
361
362 if (!handle) {
363 LOG_INFO("dlerror: %s", dlerror());
364 return false;
365 }
366
367 m->mad_stream_init = dlsym(handle, "mad_stream_init");
368 m->mad_frame_init = dlsym(handle, "mad_frame_init");
369 m->mad_synth_init = dlsym(handle, "mad_synth_init");
370 m->mad_frame_finish = dlsym(handle, "mad_frame_finish");
371 m->mad_stream_finish = dlsym(handle, "mad_stream_finish");
372 m->mad_stream_buffer = dlsym(handle, "mad_stream_buffer");
373 m->mad_frame_decode = dlsym(handle, "mad_frame_decode");
374 m->mad_synth_frame = dlsym(handle, "mad_synth_frame");
375 m->mad_stream_errorstr = dlsym(handle, "mad_stream_errorstr");
376
377 if ((err = dlerror()) != NULL) {
378 LOG_INFO("dlerror: %s", err);
379 return false;
380 }
381
382 LOG_INFO("loaded "LIBMAD);
383 #endif
384
385 return true;
386 }
387
388 struct codec *register_mad(void) {
389 static struct codec ret = {
390 'm', // id
391 "mp3", // types
392 READBUF_SIZE, // min read
393 206800, // min space
394 mad_open, // open
395 mad_close, // close
396 mad_decode, // decode
397 };
398
399 m = malloc(sizeof(struct mad));
400 if (!m) {
401 return NULL;
402 }
403
404 m->readbuf = NULL;
405 m->readbuf_len = 0;
406
407 if (!load_mad()) {
408 return NULL;
409 }
410
411 LOG_INFO("using mad to decode mp3");
412 return &ret;
413 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 #include <signal.h>
23
24 #define TITLE "Squeezelite " VERSION ", Copyright 2012-2015 Adrian Smith."
25
26 #define CODECS_BASE "flac,pcm,mp3,ogg,aac"
27 #if FFMPEG
28 #define CODECS_FF ",wma,alac"
29 #else
30 #define CODECS_FF ""
31 #endif
32 #if DSD
33 #define CODECS_DSD ",dsd"
34 #else
35 #define CODECS_DSD ""
36 #endif
37 #define CODECS_MP3 " (mad,mpg for specific mp3 codec)"
38
39 #define CODECS CODECS_BASE CODECS_FF CODECS_DSD CODECS_MP3
40
41 static void usage(const char *argv0) {
42 printf(TITLE " See -t for license terms\n"
43 "Usage: %s [options]\n"
44 " -s <server>[:<port>]\tConnect to specified server, otherwise uses autodiscovery to find server\n"
45 " -o <output device>\tSpecify output device, default \"default\", - = output to stdout\n"
46 " -l \t\t\tList output devices\n"
47 #if ALSA
48 " -a <b>:<p>:<f>:<m>\tSpecify ALSA params to open output device, b = buffer time in ms or size in bytes, p = period count or size in bytes, f sample format (16|24|24_3|32), m = use mmap (0|1)\n"
49 #endif
50 #if PORTAUDIO
51 #if OSX
52 " -a <l>:<r>\t\tSpecify Portaudio params to open output device, l = target latency in ms, r = allow OSX to resample (0|1)\n"
53 #else
54 " -a <l>\t\tSpecify Portaudio params to open output device, l = target latency in ms\n"
55 #endif
56 #endif
57 " -a <f>\t\tSpecify sample format (16|24|32) of output file when using -o - to output samples to stdout (interleaved little endian only)\n"
58 " -b <stream>:<output>\tSpecify internal Stream and Output buffer sizes in Kbytes\n"
59 " -c <codec1>,<codec2>\tRestrict codecs to those specified, otherwise load all available codecs; known codecs: " CODECS "\n"
60 " -C <timeout>\t\tClose output device when idle after timeout seconds, default is to keep it open while player is 'on'\n"
61 #if !IR
62 " -d <log>=<level>\tSet logging level, logs: all|slimproto|stream|decode|output, level: info|debug|sdebug\n"
63 #else
64 " -d <log>=<level>\tSet logging level, logs: all|slimproto|stream|decode|output|ir, level: info|debug|sdebug\n"
65 #endif
66 " -e <codec1>,<codec2>\tExplicitly exclude native support of one or more codecs; known codecs: " CODECS "\n"
67 " -f <logfile>\t\tWrite debug to logfile\n"
68 #if IR
69 " -i [<filename>]\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n"
70 #endif
71 " -m <mac addr>\t\tSet mac address, format: ab:cd:ef:12:34:56\n"
72 " -M <modelname>\tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n"
73 " -n <name>\t\tSet the player name\n"
74 " -N <filename>\t\tStore player name in filename to allow server defined name changes to be shared between servers (not supported with -n)\n"
75 #if ALSA
76 " -p <priority>\t\tSet real time priority of output thread (1-99)\n"
77 #endif
78 #if LINUX || FREEBSD
79 " -P <filename>\t\tStore the process id (PID) in filename\n"
80 #endif
81 " -r <rates>[:<delay>]\tSample rates supported, allows output to be off when squeezelite is started; rates = <maxrate>|<minrate>-<maxrate>|<rate1>,<rate2>,<rate3>; delay = optional delay switching rates in ms\n"
82 #if RESAMPLE
83 " -R -u [params]\tResample, params = <recipe>:<flags>:<attenuation>:<precision>:<passband_end>:<stopband_start>:<phase_response>,\n"
84 " \t\t\t recipe = (v|h|m|l|q)(L|I|M)(s) [E|X], E = exception - resample only if native rate not supported, X = async - resample to max rate for device, otherwise to max sync rate\n"
85 " \t\t\t flags = num in hex,\n"
86 " \t\t\t attenuation = attenuation in dB to apply (default is -1db if not explicitly set),\n"
87 " \t\t\t precision = number of bits precision (NB. HQ = 20. VHQ = 28),\n"
88 " \t\t\t passband_end = number in percent (0dB pt. bandwidth to preserve. nyquist = 100%%),\n"
89 " \t\t\t stopband_start = number in percent (Aliasing/imaging control. > passband_end),\n"
90 " \t\t\t phase_response = 0-100 (0 = minimum / 50 = linear / 100 = maximum)\n"
91 #endif
92 #if DSD
93 " -D [delay]\t\tOutput device supports DSD over PCM (DoP), delay = optional delay switching between PCM and DoP in ms\n"
94 #endif
95 #if VISEXPORT
96 " -v \t\t\tVisualiser support\n"
97 #endif
98 # if ALSA
99 " -L \t\t\tList volume controls for output device\n"
100 " -U <control>\t\tUnmute ALSA control and set to full volume (not supported with -V)\n"
101 " -V <control>\t\tUse ALSA control for volume adjustment, otherwise use software volume adjustment\n"
102 #endif
103 #if LINUX || FREEBSD
104 " -z \t\t\tDaemonize\n"
105 #endif
106 " -t \t\t\tLicense terms\n"
107 " -? \t\t\tDisplay this help text\n"
108 "\n"
109 "Build options:"
110 #if LINUX
111 " LINUX"
112 #endif
113 #if WIN
114 " WIN"
115 #endif
116 #if OSX
117 " OSX"
118 #endif
119 #if FREEBSD
120 " FREEBSD"
121 #endif
122 #if ALSA
123 " ALSA"
124 #endif
125 #if PORTAUDIO
126 " PORTAUDIO"
127 #endif
128 #if EVENTFD
129 " EVENTFD"
130 #endif
131 #if SELFPIPE
132 " SELFPIPE"
133 #endif
134 #if WINEVENT
135 " WINEVENT"
136 #endif
137 #if RESAMPLE_MP
138 " RESAMPLE_MP"
139 #else
140 #if RESAMPLE
141 " RESAMPLE"
142 #endif
143 #endif
144 #if FFMPEG
145 " FFMPEG"
146 #endif
147 #if VISEXPORT
148 " VISEXPORT"
149 #endif
150 #if IR
151 " IR"
152 #endif
153 #if DSD
154 " DSD"
155 #endif
156 #if LINKALL
157 " LINKALL"
158 #endif
159 "\n\n",
160 argv0);
161 }
162
163 static void license(void) {
164 printf(TITLE "\n\n"
165 "This program is free software: you can redistribute it and/or modify\n"
166 "it under the terms of the GNU General Public License as published by\n"
167 "the Free Software Foundation, either version 3 of the License, or\n"
168 "(at your option) any later version.\n\n"
169 "This program is distributed in the hope that it will be useful,\n"
170 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
171 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
172 "GNU General Public License for more details.\n\n"
173 "You should have received a copy of the GNU General Public License\n"
174 "along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n"
175 #if DSD
176 "Contains dsd2pcm library Copyright 2009, 2011 Sebastian Gesemann which\n"
177 "is subject to its own license.\n\n"
178 #endif
179 );
180 }
181
182 static void sighandler(int signum) {
183 slimproto_stop();
184
185 // remove ourselves in case above does not work, second SIGINT will cause non gracefull shutdown
186 signal(signum, SIG_DFL);
187 }
188
189 int main(int argc, char **argv) {
190 char *server = NULL;
191 char *output_device = "default";
192 char *include_codecs = NULL;
193 char *exclude_codecs = "";
194 char *name = NULL;
195 char *namefile = NULL;
196 char *modelname = NULL;
197 char *logfile = NULL;
198 u8_t mac[6];
199 unsigned stream_buf_size = STREAMBUF_SIZE;
200 unsigned output_buf_size = 0; // set later
201 unsigned rates[MAX_SUPPORTED_SAMPLERATES] = { 0 };
202 unsigned rate_delay = 0;
203 char *resample = NULL;
204 char *output_params = NULL;
205 unsigned idle = 0;
206 #if LINUX || FREEBSD
207 bool daemonize = false;
208 char *pidfile = NULL;
209 FILE *pidfp = NULL;
210 #endif
211 #if ALSA
212 unsigned rt_priority = OUTPUT_RT_PRIORITY;
213 char *output_mixer = NULL;
214 bool output_mixer_unmute = false;
215 #endif
216 #if DSD
217 bool dop = false;
218 unsigned dop_delay = 0;
219 #endif
220 #if VISEXPORT
221 bool visexport = false;
222 #endif
223 #if IR
224 char *lircrc = NULL;
225 #endif
226
227 log_level log_output = lWARN;
228 log_level log_stream = lWARN;
229 log_level log_decode = lWARN;
230 log_level log_slimproto = lWARN;
231 #if IR
232 log_level log_ir = lWARN;
233 #endif
234
235 char *optarg = NULL;
236 int optind = 1;
237 int i;
238
239 #define MAXCMDLINE 512
240 char cmdline[MAXCMDLINE] = "";
241
242 get_mac(mac);
243
244 for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) {
245 strcat(cmdline, argv[i]);
246 strcat(cmdline, " ");
247 }
248
249 while (optind < argc && strlen(argv[optind]) >= 2 && argv[optind][0] == '-') {
250 char *opt = argv[optind] + 1;
251 if (strstr("oabcCdefmMnNpPrs"
252 #if ALSA
253 "UV"
254 #endif
255 , opt) && optind < argc - 1) {
256 optarg = argv[optind + 1];
257 optind += 2;
258 } else if (strstr("ltz?"
259 #if ALSA
260 "L"
261 #endif
262 #if RESAMPLE
263 "uR"
264 #endif
265 #if DSD
266 "D"
267 #endif
268 #if VISEXPORT
269 "v"
270 #endif
271 #if IR
272 "i"
273 #endif
274
275 , opt)) {
276 optarg = NULL;
277 optind += 1;
278 } else {
279 fprintf(stderr, "\nOption error: -%s\n\n", opt);
280 usage(argv[0]);
281 exit(1);
282 }
283
284 switch (opt[0]) {
285 case 'o':
286 output_device = optarg;
287 break;
288 case 'a':
289 output_params = optarg;
290 break;
291 case 'b':
292 {
293 char *s = next_param(optarg, ':');
294 char *o = next_param(NULL, ':');
295 if (s) stream_buf_size = atoi(s) * 1024;
296 if (o) output_buf_size = atoi(o) * 1024;
297 }
298 break;
299 case 'c':
300 include_codecs = optarg;
301 break;
302 case 'C':
303 if (atoi(optarg) > 0) {
304 idle = atoi(optarg) * 1000;
305 }
306 break;
307 case 'e':
308 exclude_codecs = optarg;
309 break;
310 case 'd':
311 {
312 char *l = strtok(optarg, "=");
313 char *v = strtok(NULL, "=");
314 log_level new = lWARN;
315 if (l && v) {
316 if (!strcmp(v, "info")) new = lINFO;
317 if (!strcmp(v, "debug")) new = lDEBUG;
318 if (!strcmp(v, "sdebug")) new = lSDEBUG;
319 if (!strcmp(l, "all") || !strcmp(l, "slimproto")) log_slimproto = new;
320 if (!strcmp(l, "all") || !strcmp(l, "stream")) log_stream = new;
321 if (!strcmp(l, "all") || !strcmp(l, "decode")) log_decode = new;
322 if (!strcmp(l, "all") || !strcmp(l, "output")) log_output = new;
323 #if IR
324 if (!strcmp(l, "all") || !strcmp(l, "ir")) log_ir = new;
325 #endif
326 } else {
327 fprintf(stderr, "\nDebug settings error: -d %s\n\n", optarg);
328 usage(argv[0]);
329 exit(1);
330 }
331 }
332 break;
333 case 'f':
334 logfile = optarg;
335 break;
336 case 'm':
337 {
338 int byte = 0;
339 char *tmp;
340 if (!strncmp(optarg, "00:04:20", 8)) {
341 LOG_ERROR("ignoring mac address from hardware player range 00:04:20:**:**:**");
342 } else {
343 char *t = strtok(optarg, ":");
344 while (t && byte < 6) {
345 mac[byte++] = (u8_t)strtoul(t, &tmp, 16);
346 t = strtok(NULL, ":");
347 }
348 }
349 }
350 break;
351 case 'M':
352 modelname = optarg;
353 break;
354 case 'r':
355 {
356 char *rstr = next_param(optarg, ':');
357 char *dstr = next_param(NULL, ':');
358 if (rstr && strstr(rstr, ",")) {
359 // parse sample rates and sort them
360 char *r = next_param(rstr, ',');
361 unsigned tmp[MAX_SUPPORTED_SAMPLERATES] = { 0 };
362 int i, j;
363 int last = 999999;
364 for (i = 0; r && i < MAX_SUPPORTED_SAMPLERATES; ++i) {
365 tmp[i] = atoi(r);
366 r = next_param(NULL, ',');
367 }
368 for (i = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
369 int largest = 0;
370 for (j = 0; j < MAX_SUPPORTED_SAMPLERATES; ++j) {
371 if (tmp[j] > largest && tmp[j] < last) {
372 largest = tmp[j];
373 }
374 }
375 rates[i] = last = largest;
376 }
377 } else if (rstr) {
378 // optstr is <min>-<max> or <max>, extract rates from test rates within this range
379 unsigned ref[] TEST_RATES;
380 char *str1 = next_param(rstr, '-');
381 char *str2 = next_param(NULL, '-');
382 unsigned max = str2 ? atoi(str2) : (str1 ? atoi(str1) : ref[0]);
383 unsigned min = str1 && str2 ? atoi(str1) : 0;
384 unsigned tmp;
385 int i, j;
386 if (max < min) { tmp = max; max = min; min = tmp; }
387 rates[0] = max;
388 for (i = 0, j = 1; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
389 if (ref[i] < rates[j-1] && ref[i] >= min) {
390 rates[j++] = ref[i];
391 }
392 }
393 }
394 if (dstr) {
395 rate_delay = atoi(dstr);
396 }
397 }
398 break;
399 case 's':
400 server = optarg;
401 break;
402 case 'n':
403 name = optarg;
404 break;
405 case 'N':
406 namefile = optarg;
407 break;
408 #if ALSA
409 case 'p':
410 rt_priority = atoi(optarg);
411 if (rt_priority > 99 || rt_priority < 1) {
412 fprintf(stderr, "\nError: invalid priority: %s\n\n", optarg);
413 usage(argv[0]);
414 exit(1);
415 }
416 break;
417 #endif
418 #if LINUX || FREEBSD
419 case 'P':
420 pidfile = optarg;
421 break;
422 #endif
423 case 'l':
424 list_devices();
425 exit(0);
426 break;
427 #if ALSA
428 case 'L':
429 list_mixers(output_device);
430 exit(0);
431 break;
432 #endif
433 #if RESAMPLE
434 case 'u':
435 case 'R':
436 if (optind < argc && argv[optind] && argv[optind][0] != '-') {
437 resample = argv[optind++];
438 } else {
439 resample = "";
440 }
441 break;
442 #endif
443 #if DSD
444 case 'D':
445 dop = true;
446 if (optind < argc && argv[optind] && argv[optind][0] != '-') {
447 dop_delay = atoi(argv[optind++]);
448 }
449 break;
450 #endif
451 #if VISEXPORT
452 case 'v':
453 visexport = true;
454 break;
455 #endif
456 #if ALSA
457 case 'U':
458 output_mixer_unmute = true;
459 case 'V':
460 if (output_mixer) {
461 fprintf(stderr, "-U and -V option should not be used at same time\n");
462 exit(1);
463 }
464 output_mixer = optarg;
465 break;
466 #endif
467 #if IR
468 case 'i':
469 if (optind < argc && argv[optind] && argv[optind][0] != '-') {
470 lircrc = argv[optind++];
471 } else {
472 lircrc = "~/.lircrc"; // liblirc_client will expand ~/
473 }
474 break;
475 #endif
476 #if LINUX || FREEBSD
477 case 'z':
478 daemonize = true;
479 break;
480 #endif
481 case 't':
482 license();
483 exit(0);
484 case '?':
485 usage(argv[0]);
486 exit(0);
487 default:
488 fprintf(stderr, "Arg error: %s\n", argv[optind]);
489 break;
490 }
491 }
492
493 // warn if command line includes something which isn't parsed
494 if (optind < argc) {
495 fprintf(stderr, "\nError: command line argument error\n\n");
496 usage(argv[0]);
497 exit(1);
498 }
499
500 signal(SIGINT, sighandler);
501 signal(SIGTERM, sighandler);
502 #if defined(SIGQUIT)
503 signal(SIGQUIT, sighandler);
504 #endif
505 #if defined(SIGHUP)
506 signal(SIGHUP, sighandler);
507 #endif
508
509 // set the output buffer size if not specified on the command line, take account of resampling
510 if (!output_buf_size) {
511 output_buf_size = OUTPUTBUF_SIZE;
512 if (resample) {
513 unsigned scale = 8;
514 if (rates[0]) {
515 scale = rates[0] / 44100;
516 if (scale > 8) scale = 8;
517 if (scale < 1) scale = 1;
518 }
519 output_buf_size *= scale;
520 }
521 }
522
523 if (logfile) {
524 if (!freopen(logfile, "a", stderr)) {
525 fprintf(stderr, "error opening logfile %s: %s\n", logfile, strerror(errno));
526 } else {
527 if (log_output >= lINFO || log_stream >= lINFO || log_decode >= lINFO || log_slimproto >= lINFO) {
528 fprintf(stderr, "\n%s\n", cmdline);
529 }
530 }
531 }
532
533 #if LINUX || FREEBSD
534 if (pidfile) {
535 if (!(pidfp = fopen(pidfile, "w")) ) {
536 fprintf(stderr, "Error opening pidfile %s: %s\n", pidfile, strerror(errno));
537 exit(1);
538 }
539 pidfile = realpath(pidfile, NULL); // daemonize will change cwd
540 }
541
542 if (daemonize) {
543 if (daemon(0, logfile ? 1 : 0)) {
544 fprintf(stderr, "error daemonizing: %s\n", strerror(errno));
545 }
546 }
547
548 if (pidfp) {
549 fprintf(pidfp, "%d\n", getpid());
550 fclose(pidfp);
551 }
552 #endif
553
554 #if WIN
555 winsock_init();
556 #endif
557
558 stream_init(log_stream, stream_buf_size);
559
560 if (!strcmp(output_device, "-")) {
561 output_init_stdout(log_output, output_buf_size, output_params, rates, rate_delay);
562 } else {
563 #if ALSA
564 output_init_alsa(log_output, output_device, output_buf_size, output_params, rates, rate_delay, rt_priority, idle, output_mixer,
565 output_mixer_unmute);
566 #endif
567 #if PORTAUDIO
568 output_init_pa(log_output, output_device, output_buf_size, output_params, rates, rate_delay, idle);
569 #endif
570 }
571
572 #if DSD
573 dop_init(dop, dop_delay);
574 #endif
575
576 #if VISEXPORT
577 if (visexport) {
578 output_vis_init(log_output, mac);
579 }
580 #endif
581
582 decode_init(log_decode, include_codecs, exclude_codecs);
583
584 #if RESAMPLE
585 if (resample) {
586 process_init(resample);
587 }
588 #endif
589
590 #if IR
591 if (lircrc) {
592 ir_init(log_ir, lircrc);
593 }
594 #endif
595
596 if (name && namefile) {
597 fprintf(stderr, "-n and -N option should not be used at same time\n");
598 exit(1);
599 }
600
601 slimproto(log_slimproto, server, mac, name, namefile, modelname);
602
603 decode_close();
604 stream_close();
605
606 if (!strcmp(output_device, "-")) {
607 output_close_stdout();
608 } else {
609 #if ALSA
610 output_close_alsa();
611 #endif
612 #if PORTAUDIO
613 output_close_pa();
614 #endif
615 }
616
617 #if IR
618 ir_close();
619 #endif
620
621 #if WIN
622 winsock_close();
623 #endif
624
625 #if LINUX || FREEBSD
626 if (pidfile) {
627 unlink(pidfile);
628 free(pidfile);
629 }
630 #endif
631
632 exit(0);
633 }
+276
-0
mpg.c less more
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 #include <mpg123.h>
23
24 #define READ_SIZE 512
25 #define WRITE_SIZE 32 * 1024
26
27 struct mpg {
28 mpg123_handle *h;
29 bool use16bit;
30 #if !LINKALL
31 // mpg symbols to be dynamically loaded
32 int (* mpg123_init)(void);
33 int (* mpg123_feature)(const enum mpg123_feature_set);
34 void (* mpg123_rates)(const long **, size_t *);
35 int (* mpg123_format_none)(mpg123_handle *);
36 int (* mpg123_format)(mpg123_handle *, long, int, int);
37 mpg123_handle *(* mpg123_new)(const char*, int *);
38 void (* mpg123_delete)(mpg123_handle *);
39 int (* mpg123_open_feed)(mpg123_handle *);
40 int (* mpg123_decode)(mpg123_handle *, const unsigned char *, size_t, unsigned char *, size_t, size_t *);
41 int (* mpg123_getformat)(mpg123_handle *, long *, int *, int *);
42 const char* (* mpg123_plain_strerror)(int);
43 #endif
44 };
45
46 static struct mpg *m;
47
48 extern log_level loglevel;
49
50 extern struct buffer *streambuf;
51 extern struct buffer *outputbuf;
52 extern struct streamstate stream;
53 extern struct outputstate output;
54 extern struct decodestate decode;
55 extern struct processstate process;
56
57 #define LOCK_S mutex_lock(streambuf->mutex)
58 #define UNLOCK_S mutex_unlock(streambuf->mutex)
59 #define LOCK_O mutex_lock(outputbuf->mutex)
60 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
61 #if PROCESS
62 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
63 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
64 #define LOCK_O_not_direct if (!decode.direct) mutex_lock(outputbuf->mutex)
65 #define UNLOCK_O_not_direct if (!decode.direct) mutex_unlock(outputbuf->mutex)
66 #define IF_DIRECT(x) if (decode.direct) { x }
67 #define IF_PROCESS(x) if (!decode.direct) { x }
68 #else
69 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
70 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
71 #define LOCK_O_not_direct
72 #define UNLOCK_O_not_direct
73 #define IF_DIRECT(x) { x }
74 #define IF_PROCESS(x)
75 #endif
76
77 #if LINKALL
78 #define MPG123(h, fn, ...) (mpg123_ ## fn)(__VA_ARGS__)
79 #else
80 #define MPG123(h, fn, ...) (h)->mpg123_##fn(__VA_ARGS__)
81 #endif
82
83 static decode_state mpg_decode(void) {
84 size_t bytes, space, size;
85 int ret;
86 u8_t *write_buf;
87
88 LOCK_S;
89 LOCK_O_direct;
90 bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
91
92 IF_DIRECT(
93 space = min(_buf_space(outputbuf), _buf_cont_write(outputbuf));
94 write_buf = outputbuf->writep;
95 );
96 IF_PROCESS(
97 space = process.max_in_frames;
98 write_buf = process.inbuf;
99 );
100
101 bytes = min(bytes, READ_SIZE);
102 space = min(space, WRITE_SIZE);
103
104 if (m->use16bit) {
105 space = (space / BYTES_PER_FRAME) * 4;
106 }
107
108 // only get the new stream information on first call so we can reset decode.direct appropriately
109 if (decode.new_stream) {
110 space = 0;
111 }
112
113 ret = MPG123(m, decode, m->h, streambuf->readp, bytes, write_buf, space, &size);
114
115 if (ret == MPG123_NEW_FORMAT) {
116
117 if (decode.new_stream) {
118 long rate;
119 int channels, enc;
120
121 MPG123(m, getformat, m->h, &rate, &channels, &enc);
122
123 LOG_INFO("setting track_start");
124 LOCK_O_not_direct;
125 output.next_sample_rate = decode_newstream(rate, output.supported_rates);
126 IF_DSD( output.next_dop = false; )
127 output.track_start = outputbuf->writep;
128 if (output.fade_mode) _checkfade(true);
129 decode.new_stream = false;
130 UNLOCK_O_not_direct;
131
132 } else {
133 LOG_WARN("format change mid stream - not supported");
134 }
135 }
136
137 // expand 16bit output to 32bit samples
138 if (m->use16bit) {
139 s16_t *iptr;
140 s32_t *optr;
141 size_t count = size / 2;
142 size = count * 4;
143 iptr = (s16_t *)write_buf + count;
144 optr = (s32_t *)write_buf + count;
145 while (count--) {
146 *--optr = *--iptr << 16;
147 }
148 }
149
150 _buf_inc_readp(streambuf, bytes);
151
152 IF_DIRECT(
153 _buf_inc_writep(outputbuf, size);
154 );
155 IF_PROCESS(
156 process.in_frames = size / BYTES_PER_FRAME;
157 );
158
159 UNLOCK_O_direct;
160
161 LOG_SDEBUG("write %u frames", size / BYTES_PER_FRAME);
162
163 if (ret == MPG123_DONE || (bytes == 0 && size == 0 && stream.state <= DISCONNECT)) {
164 UNLOCK_S;
165 LOG_INFO("stream complete");
166 return DECODE_COMPLETE;
167 }
168
169 UNLOCK_S;
170
171 if (ret == MPG123_ERR) {
172 LOG_WARN("Error");
173 return DECODE_COMPLETE;
174 }
175
176 // OK and NEED_MORE keep running
177 return DECODE_RUNNING;
178 }
179
180 static void mpg_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
181 int err;
182 const long *list;
183 size_t count, i;
184
185 if (m->h) {
186 MPG123(m, delete, m->h);
187 }
188
189 m->h = MPG123(m, new, NULL, &err);
190
191 if (m->h == NULL) {
192 LOG_WARN("new error: %s", MPG123(m, plain_strerror, err));
193 }
194
195 // restrict output to 32bit or 16bit signed 2 channel based on library capability
196 MPG123(m, rates, &list, &count);
197 MPG123(m, format_none, m->h);
198 for (i = 0; i < count; i++) {
199 MPG123(m, format, m->h, list[i], 2, m->use16bit ? MPG123_ENC_SIGNED_16 : MPG123_ENC_SIGNED_32);
200 }
201
202 err = MPG123(m, open_feed, m->h);
203
204 if (err) {
205 LOG_WARN("open feed error: %s", MPG123(m, plain_strerror, err));
206 }
207 }
208
209 static void mpg_close(void) {
210 MPG123(m, delete, m->h);
211 m->h = NULL;
212 }
213
214 static bool load_mpg() {
215 #if !LINKALL
216 void *handle = dlopen(LIBMPG, RTLD_NOW);
217 char *err;
218
219 if (!handle) {
220 LOG_INFO("dlerror: %s", dlerror());
221 return false;
222 }
223
224 m->mpg123_init = dlsym(handle, "mpg123_init");
225 m->mpg123_feature = dlsym(handle, "mpg123_feature");
226 m->mpg123_rates = dlsym(handle, "mpg123_rates");
227 m->mpg123_format_none = dlsym(handle, "mpg123_format_none");
228 m->mpg123_format = dlsym(handle, "mpg123_format");
229 m->mpg123_new = dlsym(handle, "mpg123_new");
230 m->mpg123_delete = dlsym(handle, "mpg123_delete");
231 m->mpg123_open_feed = dlsym(handle, "mpg123_open_feed");
232 m->mpg123_decode = dlsym(handle, "mpg123_decode");
233 m->mpg123_getformat = dlsym(handle, "mpg123_getformat");
234 m->mpg123_plain_strerror = dlsym(handle, "mpg123_plain_strerror");
235
236 if ((err = dlerror()) != NULL) {
237 LOG_INFO("dlerror: %s", err);
238 return false;
239 }
240
241 LOG_INFO("loaded "LIBMPG);
242 #endif
243
244 return true;
245 }
246
247 struct codec *register_mpg(void) {
248 static struct codec ret = {
249 'm', // id
250 "mp3", // types
251 READ_SIZE, // min read
252 WRITE_SIZE, // min space
253 mpg_open, // open
254 mpg_close, // close
255 mpg_decode, // decode
256 };
257
258 m = malloc(sizeof(struct mpg));
259 if (!m) {
260 return NULL;
261 }
262
263 m->h = NULL;
264
265 if (!load_mpg()) {
266 return NULL;
267 }
268
269 MPG123(m, init);
270
271 m->use16bit = MPG123(m, feature, MPG123_FEATURE_OUTPUT_32BIT);
272
273 LOG_INFO("using mpg to decode mp3");
274 return &ret;
275 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // Common output function
21
22 #include "squeezelite.h"
23
24 static log_level loglevel;
25
26 struct outputstate output;
27
28 static struct buffer buf;
29
30 struct buffer *outputbuf = &buf;
31
32 u8_t *silencebuf;
33 #if DSD
34 u8_t *silencebuf_dop;
35 #endif
36
37 #define LOCK mutex_lock(outputbuf->mutex)
38 #define UNLOCK mutex_unlock(outputbuf->mutex)
39
40 // functions starting _* are called with mutex locked
41
42 frames_t _output_frames(frames_t avail) {
43
44 frames_t frames, size;
45 bool silence;
46
47 s32_t cross_gain_in = 0, cross_gain_out = 0; s32_t *cross_ptr = NULL;
48
49 s32_t gainL = output.current_replay_gain ? gain(output.gainL, output.current_replay_gain) : output.gainL;
50 s32_t gainR = output.current_replay_gain ? gain(output.gainR, output.current_replay_gain) : output.gainR;
51
52 if (output.invert) { gainL = -gainL; gainR = -gainR; }
53
54 frames = _buf_used(outputbuf) / BYTES_PER_FRAME;
55 silence = false;
56
57 // start when threshold met
58 if (output.state == OUTPUT_BUFFER && frames > output.threshold * output.next_sample_rate / 100 && frames > output.start_frames) {
59 output.state = OUTPUT_RUNNING;
60 LOG_INFO("start buffer frames: %u", frames);
61 wake_controller();
62 }
63
64 // skip ahead - consume outputbuf but play nothing
65 if (output.state == OUTPUT_SKIP_FRAMES) {
66 if (frames > 0) {
67 frames_t skip = min(frames, output.skip_frames);
68 LOG_INFO("skip %u of %u frames", skip, output.skip_frames);
69 frames -= skip;
70 output.frames_played += skip;
71 while (skip > 0) {
72 frames_t cont_frames = min(skip, _buf_cont_read(outputbuf) / BYTES_PER_FRAME);
73 skip -= cont_frames;
74 _buf_inc_readp(outputbuf, cont_frames * BYTES_PER_FRAME);
75 }
76 }
77 output.state = OUTPUT_RUNNING;
78 }
79
80 // pause frames - play silence for required frames
81 if (output.state == OUTPUT_PAUSE_FRAMES) {
82 LOG_INFO("pause %u frames", output.pause_frames);
83 if (output.pause_frames == 0) {
84 output.state = OUTPUT_RUNNING;
85 } else {
86 silence = true;
87 frames = min(avail, output.pause_frames);
88 frames = min(frames, MAX_SILENCE_FRAMES);
89 output.pause_frames -= frames;
90 }
91 }
92
93 // start at - play silence until jiffies reached
94 if (output.state == OUTPUT_START_AT) {
95 u32_t now = gettime_ms();
96 if (now >= output.start_at || output.start_at > now + 10000) {
97 output.state = OUTPUT_RUNNING;
98 } else {
99 u32_t delta_frames = (output.start_at - now) * output.current_sample_rate / 1000;
100 silence = true;
101 frames = min(avail, delta_frames);
102 frames = min(frames, MAX_SILENCE_FRAMES);
103 }
104 }
105
106 // play silence if buffering or no frames
107 if (output.state <= OUTPUT_BUFFER || frames == 0) {
108 silence = true;
109 frames = min(avail, MAX_SILENCE_FRAMES);
110 }
111
112 LOG_SDEBUG("avail: %d frames: %d silence: %d", avail, frames, silence);
113 frames = min(frames, avail);
114 size = frames;
115
116 while (size > 0) {
117 frames_t out_frames;
118 frames_t cont_frames = _buf_cont_read(outputbuf) / BYTES_PER_FRAME;
119 int wrote;
120
121 if (output.track_start && !silence) {
122 if (output.track_start == outputbuf->readp) {
123 unsigned delay = 0;
124 if (output.current_sample_rate != output.next_sample_rate) {
125 delay = output.rate_delay;
126 }
127 IF_DSD(
128 if (output.dop != output.next_dop) {
129 delay = output.dop_delay;
130 }
131 )
132 frames -= size;
133 // add silence delay in two halves, before and after track start on rate or pcm-dop change
134 if (delay) {
135 output.state = OUTPUT_PAUSE_FRAMES;
136 if (!output.delay_active) {
137 output.pause_frames = output.current_sample_rate * delay / 2000;
138 output.delay_active = true; // first delay - don't process track start
139 break;
140 } else {
141 output.pause_frames = output.next_sample_rate * delay / 2000;
142 output.delay_active = false; // second delay - process track start
143 }
144 }
145 LOG_INFO("track start sample rate: %u replay_gain: %u", output.next_sample_rate, output.next_replay_gain);
146 output.frames_played = 0;
147 output.track_started = true;
148 output.track_start_time = gettime_ms();
149 output.current_sample_rate = output.next_sample_rate;
150 IF_DSD(
151 output.dop = output.next_dop;
152 )
153 if (!output.fade == FADE_ACTIVE || !output.fade_mode == FADE_CROSSFADE) {
154 output.current_replay_gain = output.next_replay_gain;
155 }
156 output.track_start = NULL;
157 break;
158 } else if (output.track_start > outputbuf->readp) {
159 // reduce cont_frames so we find the next track start at beginning of next chunk
160 cont_frames = min(cont_frames, (output.track_start - outputbuf->readp) / BYTES_PER_FRAME);
161 }
162 }
163
164 IF_DSD(
165 if (output.dop) {
166 gainL = gainR = FIXED_ONE;
167 }
168 )
169
170 if (output.fade && !silence) {
171 if (output.fade == FADE_DUE) {
172 if (output.fade_start == outputbuf->readp) {
173 LOG_INFO("fade start reached");
174 output.fade = FADE_ACTIVE;
175 } else if (output.fade_start > outputbuf->readp) {
176 cont_frames = min(cont_frames, (output.fade_start - outputbuf->readp) / BYTES_PER_FRAME);
177 }
178 }
179 if (output.fade == FADE_ACTIVE) {
180 // find position within fade
181 frames_t cur_f = outputbuf->readp >= output.fade_start ? (outputbuf->readp - output.fade_start) / BYTES_PER_FRAME :
182 (outputbuf->readp + outputbuf->size - output.fade_start) / BYTES_PER_FRAME;
183 frames_t dur_f = output.fade_end >= output.fade_start ? (output.fade_end - output.fade_start) / BYTES_PER_FRAME :
184 (output.fade_end + outputbuf->size - output.fade_start) / BYTES_PER_FRAME;
185 if (cur_f >= dur_f) {
186 if (output.fade_mode == FADE_INOUT && output.fade_dir == FADE_DOWN) {
187 LOG_INFO("fade down complete, starting fade up");
188 output.fade_dir = FADE_UP;
189 output.fade_start = outputbuf->readp;
190 output.fade_end = outputbuf->readp + dur_f * BYTES_PER_FRAME;
191 if (output.fade_end >= outputbuf->wrap) {
192 output.fade_end -= outputbuf->size;
193 }
194 cur_f = 0;
195 } else if (output.fade_mode == FADE_CROSSFADE) {
196 LOG_INFO("crossfade complete");
197 if (_buf_used(outputbuf) >= dur_f * BYTES_PER_FRAME) {
198 _buf_inc_readp(outputbuf, dur_f * BYTES_PER_FRAME);
199 LOG_INFO("skipped crossfaded start");
200 } else {
201 LOG_WARN("unable to skip crossfaded start");
202 }
203 output.fade = FADE_INACTIVE;
204 output.current_replay_gain = output.next_replay_gain;
205 } else {
206 LOG_INFO("fade complete");
207 output.fade = FADE_INACTIVE;
208 }
209 }
210 // if fade in progress set fade gain, ensure cont_frames reduced so we get to end of fade at start of chunk
211 if (output.fade) {
212 if (output.fade_end > outputbuf->readp) {
213 cont_frames = min(cont_frames, (output.fade_end - outputbuf->readp) / BYTES_PER_FRAME);
214 }
215 if (output.fade_dir == FADE_UP || output.fade_dir == FADE_DOWN) {
216 // fade in, in-out, out handled via altering standard gain
217 s32_t fade_gain;
218 if (output.fade_dir == FADE_DOWN) {
219 cur_f = dur_f - cur_f;
220 }
221 fade_gain = to_gain((float)cur_f / (float)dur_f);
222 gainL = gain(gainL, fade_gain);
223 gainR = gain(gainR, fade_gain);
224 if (output.invert) { gainL = -gainL; gainR = -gainR; }
225 }
226 if (output.fade_dir == FADE_CROSS) {
227 // cross fade requires special treatment - performed later based on these values
228 // support different replay gain for old and new track by retaining old value until crossfade completes
229 if (_buf_used(outputbuf) / BYTES_PER_FRAME > dur_f + size) {
230 cross_gain_in = to_gain((float)cur_f / (float)dur_f);
231 cross_gain_out = FIXED_ONE - cross_gain_in;
232 if (output.current_replay_gain) {
233 cross_gain_out = gain(cross_gain_out, output.current_replay_gain);
234 }
235 if (output.next_replay_gain) {
236 cross_gain_in = gain(cross_gain_in, output.next_replay_gain);
237 }
238 gainL = output.gainL;
239 gainR = output.gainR;
240 if (output.invert) { gainL = -gainL; gainR = -gainR; }
241 cross_ptr = (s32_t *)(output.fade_end + cur_f * BYTES_PER_FRAME);
242 } else {
243 LOG_INFO("unable to continue crossfade - too few samples");
244 output.fade = FADE_INACTIVE;
245 }
246 }
247 }
248 }
249 }
250
251 out_frames = !silence ? min(size, cont_frames) : size;
252
253 wrote = output.write_cb(out_frames, silence, gainL, gainR, cross_gain_in, cross_gain_out, &cross_ptr);
254
255 if (wrote <= 0) {
256 frames -= size;
257 break;
258 } else {
259 out_frames = (frames_t)wrote;
260 }
261
262 size -= out_frames;
263
264 _vis_export(outputbuf, &output, out_frames, silence);
265
266 if (!silence) {
267 _buf_inc_readp(outputbuf, out_frames * BYTES_PER_FRAME);
268 output.frames_played += out_frames;
269 }
270 }
271
272 LOG_SDEBUG("wrote %u frames", frames);
273
274 return frames;
275 }
276
277 void _checkfade(bool start) {
278 frames_t bytes;
279
280 LOG_INFO("fade mode: %u duration: %u %s", output.fade_mode, output.fade_secs, start ? "track-start" : "track-end");
281
282 bytes = output.next_sample_rate * BYTES_PER_FRAME * output.fade_secs;
283 if (output.fade_mode == FADE_INOUT) {
284 bytes /= 2;
285 }
286
287 if (start && (output.fade_mode == FADE_IN || (output.fade_mode == FADE_INOUT && _buf_used(outputbuf) == 0))) {
288 bytes = min(bytes, outputbuf->size - BYTES_PER_FRAME); // shorter than full buffer otherwise start and end align
289 LOG_INFO("fade IN: %u frames", bytes / BYTES_PER_FRAME);
290 output.fade = FADE_DUE;
291 output.fade_dir = FADE_UP;
292 output.fade_start = outputbuf->writep;
293 output.fade_end = output.fade_start + bytes;
294 if (output.fade_end >= outputbuf->wrap) {
295 output.fade_end -= outputbuf->size;
296 }
297 }
298
299 if (!start && (output.fade_mode == FADE_OUT || output.fade_mode == FADE_INOUT)) {
300 bytes = min(_buf_used(outputbuf), bytes);
301 LOG_INFO("fade %s: %u frames", output.fade_mode == FADE_INOUT ? "IN-OUT" : "OUT", bytes / BYTES_PER_FRAME);
302 output.fade = FADE_DUE;
303 output.fade_dir = FADE_DOWN;
304 output.fade_start = outputbuf->writep - bytes;
305 if (output.fade_start < outputbuf->buf) {
306 output.fade_start += outputbuf->size;
307 }
308 output.fade_end = outputbuf->writep;
309 }
310
311 if (start && output.fade_mode == FADE_CROSSFADE) {
312 if (_buf_used(outputbuf) != 0) {
313 if (output.next_sample_rate != output.current_sample_rate) {
314 LOG_INFO("crossfade disabled as sample rates differ");
315 return;
316 }
317 bytes = min(bytes, _buf_used(outputbuf)); // max of current remaining samples from previous track
318 bytes = min(bytes, (frames_t)(outputbuf->size * 0.9)); // max of 90% of outputbuf as we consume additional buffer during crossfade
319 LOG_INFO("CROSSFADE: %u frames", bytes / BYTES_PER_FRAME);
320 output.fade = FADE_DUE;
321 output.fade_dir = FADE_CROSS;
322 output.fade_start = outputbuf->writep - bytes;
323 if (output.fade_start < outputbuf->buf) {
324 output.fade_start += outputbuf->size;
325 }
326 output.fade_end = outputbuf->writep;
327 output.track_start = output.fade_start;
328 } else if (outputbuf->size == OUTPUTBUF_SIZE && outputbuf->readp == outputbuf->buf) {
329 // if default setting used and nothing in buffer attempt to resize to provide full crossfade support
330 LOG_INFO("resize outputbuf for crossfade");
331 _buf_resize(outputbuf, OUTPUTBUF_SIZE_CROSSFADE);
332 #if LINUX || FREEBSD
333 touch_memory(outputbuf->buf, outputbuf->size);
334 #endif
335 }
336 }
337 }
338
339 void output_init_common(log_level level, const char *device, unsigned output_buf_size, unsigned rates[], unsigned idle) {
340 unsigned i;
341
342 loglevel = level;
343
344 output_buf_size = output_buf_size - (output_buf_size % BYTES_PER_FRAME);
345 LOG_DEBUG("outputbuf size: %u", output_buf_size);
346
347 buf_init(outputbuf, output_buf_size);
348 if (!outputbuf->buf) {
349 LOG_ERROR("unable to malloc output buffer");
350 exit(0);
351 }
352
353 silencebuf = malloc(MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
354 if (!silencebuf) {
355 LOG_ERROR("unable to malloc silence buffer");
356 exit(0);
357 }
358 memset(silencebuf, 0, MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
359
360 IF_DSD(
361 silencebuf_dop = malloc(MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
362 if (!silencebuf_dop) {
363 LOG_ERROR("unable to malloc silence dop buffer");
364 exit(0);
365 }
366 dop_silence_frames((u32_t *)silencebuf_dop, MAX_SILENCE_FRAMES);
367 )
368
369 LOG_DEBUG("idle timeout: %u", idle);
370
371 output.state = idle ? OUTPUT_OFF: OUTPUT_STOPPED;
372 output.device = device;
373 output.fade = FADE_INACTIVE;
374 output.invert = false;
375 output.error_opening = false;
376 output.idle_to = (u32_t) idle;
377
378 if (!rates[0]) {
379 if (!test_open(output.device, output.supported_rates)) {
380 LOG_ERROR("unable to open output device");
381 exit(0);
382 }
383 } else {
384 for (i = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
385 output.supported_rates[i] = rates[i];
386 }
387 }
388
389 // set initial sample rate, preferring 44100
390 for (i = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
391 if (output.supported_rates[i] == 44100) {
392 output.default_sample_rate = 44100;
393 break;
394 }
395 }
396 if (!output.default_sample_rate) {
397 output.default_sample_rate = output.supported_rates[0];
398 }
399
400 output.current_sample_rate = output.default_sample_rate;
401
402 if (loglevel >= lINFO) {
403 char rates_buf[10 * MAX_SUPPORTED_SAMPLERATES] = "";
404 for (i = 0; output.supported_rates[i]; ++i) {
405 char s[10];
406 sprintf(s, "%d ", output.supported_rates[i]);
407 strcat(rates_buf, s);
408 }
409 LOG_INFO("supported rates: %s", rates_buf);
410 }
411 }
412
413 void output_close_common(void) {
414 buf_destroy(outputbuf);
415 free(silencebuf);
416 IF_DSD(
417 free(silencebuf_dop);
418 )
419 }
420
421 void output_flush(void) {
422 LOG_INFO("flush output buffer");
423 buf_flush(outputbuf);
424 LOCK;
425 output.fade = FADE_INACTIVE;
426 if (output.state != OUTPUT_OFF) {
427 output.state = OUTPUT_STOPPED;
428 if (output.error_opening) {
429 output.current_sample_rate = output.default_sample_rate;
430 }
431 output.delay_active = false;
432 }
433 output.frames_played = 0;
434 UNLOCK;
435 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // Output using Alsa
21
22 #include "squeezelite.h"
23
24 #if ALSA
25
26 #include <alsa/asoundlib.h>
27 #include <sys/mman.h>
28 #include <malloc.h>
29 #include <math.h>
30
31 #define MAX_DEVICE_LEN 128
32
33 static snd_pcm_format_t fmts[] = { SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_S16_LE,
34 SND_PCM_FORMAT_UNKNOWN };
35
36 #if SL_LITTLE_ENDIAN
37 #define NATIVE_FORMAT SND_PCM_FORMAT_S32_LE
38 #else
39 #define NATIVE_FORMAT SND_PCM_FORMAT_S32_BE
40 #endif
41
42 // ouput device
43 static struct {
44 char device[MAX_DEVICE_LEN + 1];
45 snd_pcm_format_t format;
46 snd_pcm_uframes_t buffer_size;
47 snd_pcm_uframes_t period_size;
48 unsigned rate;
49 bool mmap;
50 bool reopen;
51 u8_t *write_buf;
52 const char *volume_mixer_name;
53 int volume_mixer_index;
54 } alsa;
55
56 static snd_pcm_t *pcmp = NULL;
57
58 extern u8_t *silencebuf;
59 #if DSD
60 extern u8_t *silencebuf_dop;
61 #endif
62
63 static log_level loglevel;
64
65 static bool running = true;
66
67 extern struct outputstate output;
68 extern struct buffer *outputbuf;
69
70 #define LOCK mutex_lock(outputbuf->mutex)
71 #define UNLOCK mutex_unlock(outputbuf->mutex)
72
73 void list_devices(void) {
74 void **hints, **n;
75 if (snd_device_name_hint(-1, "pcm", &hints) >= 0) {
76 n = hints;
77 printf("Output devices:\n");
78 while (*n) {
79 char *name = snd_device_name_get_hint(*n, "NAME");
80 char *desc = snd_device_name_get_hint(*n, "DESC");
81 if (name) printf(" %-30s", name);
82 if (desc) {
83 char *s1 = strtok(desc, "\n");
84 char *s2 = strtok(NULL, "\n");
85 if (s1) printf(" - %s", s1);
86 if (s2) printf(" - %s", s2);
87 }
88 printf("\n");
89 if (name) free(name);
90 if (desc) free(desc);
91 n++;
92 }
93 snd_device_name_free_hint(hints);
94 }
95 printf("\n");
96 }
97
98 void list_mixers(const char *output_device) {
99 int err;
100 snd_mixer_t *handle;
101 snd_mixer_selem_id_t *sid;
102 snd_mixer_elem_t *elem;
103 snd_mixer_selem_id_alloca(&sid);
104
105 LOG_INFO("listing mixers for: %s", output_device);
106
107 if ((err = snd_mixer_open(&handle, 0)) < 0) {
108 LOG_ERROR("open error: %s", snd_strerror(err));
109 return;
110 }
111 if ((err = snd_mixer_attach(handle, output_device)) < 0) {
112 LOG_ERROR("attach error: %s", snd_strerror(err));
113 snd_mixer_close(handle);
114 return;
115 }
116 if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
117 LOG_ERROR("register error: %s", snd_strerror(err));
118 snd_mixer_close(handle);
119 return;
120 }
121 if ((err = snd_mixer_load(handle)) < 0) {
122 LOG_ERROR("load error: %s", snd_strerror(err));
123 snd_mixer_close(handle);
124 return;
125 }
126
127 printf("Volume controls for %s\n", output_device);
128 for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) {
129 if (snd_mixer_selem_has_playback_volume(elem)) {
130 snd_mixer_selem_get_id(elem, sid);
131 printf(" %s", snd_mixer_selem_id_get_name(sid));
132 if (snd_mixer_selem_id_get_index(sid)) {
133 printf(",%d", snd_mixer_selem_id_get_index(sid));
134 }
135 printf("\n");
136 }
137 }
138 printf("\n");
139
140 snd_mixer_close(handle);
141 }
142
143 #define MINVOL_DB 72 // LMS volume map for SqueezePlay sends values in range ~ -72..0 dB
144
145 static void set_mixer(const char *device, const char *mixer, int mixer_index, bool setmax, float ldB, float rdB) {
146 int err;
147 long nleft, nright;
148 long min, max;
149 snd_mixer_t *handle;
150 snd_mixer_selem_id_t *sid;
151 snd_mixer_elem_t* elem;
152
153 if ((err = snd_mixer_open(&handle, 0)) < 0) {
154 LOG_ERROR("open error: %s", snd_strerror(err));
155 return;
156 }
157 if ((err = snd_mixer_attach(handle, device)) < 0) {
158 LOG_ERROR("attach error: %s", snd_strerror(err));
159 snd_mixer_close(handle);
160 return;
161 }
162 if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
163 LOG_ERROR("register error: %s", snd_strerror(err));
164 snd_mixer_close(handle);
165 return;
166 }
167 if ((err = snd_mixer_load(handle)) < 0) {
168 LOG_ERROR("load error: %s", snd_strerror(err));
169 snd_mixer_close(handle);
170 return;
171 }
172
173 snd_mixer_selem_id_alloca(&sid);
174
175 snd_mixer_selem_id_set_index(sid, mixer_index);
176 snd_mixer_selem_id_set_name(sid, mixer);
177
178 if ((elem = snd_mixer_find_selem(handle, sid)) == NULL) {
179 LOG_ERROR("error find selem %s", mixer);
180 snd_mixer_close(handle);
181 return;
182 }
183
184 if (snd_mixer_selem_has_playback_switch(elem)) {
185 snd_mixer_selem_set_playback_switch_all(elem, 1); // unmute
186 }
187
188 err = snd_mixer_selem_get_playback_dB_range(elem, &min, &max);
189
190 if (err < 0 || max - min < 1000) {
191 // unable to get db range or range is less than 10dB - ignore and set using raw values
192 if ((err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max)) < 0) {
193 LOG_ERROR("unable to get volume raw range");
194 } else {
195 long lraw, rraw;
196 if (setmax) {
197 lraw = rraw = max;
198 } else {
199 lraw = ((ldB > -MINVOL_DB ? MINVOL_DB + floor(ldB) : 0) / MINVOL_DB * (max-min)) + min;
200 rraw = ((rdB > -MINVOL_DB ? MINVOL_DB + floor(rdB) : 0) / MINVOL_DB * (max-min)) + min;
201 }
202 LOG_DEBUG("setting vol raw [%ld..%ld]", min, max);
203 if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, lraw)) < 0) {
204 LOG_ERROR("error setting left volume: %s", snd_strerror(err));
205 }
206 if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, rraw)) < 0) {
207 LOG_ERROR("error setting right volume: %s", snd_strerror(err));
208 }
209 }
210 } else {
211 // set db directly
212 LOG_DEBUG("setting vol dB [%ld..%ld]", min, max);
213 if (setmax) {
214 // set to 0dB if available as this should be max volume for music recored at max pcm values
215 if (max >= 0 && min <= 0) {
216 ldB = rdB = 0;
217 } else {
218 ldB = rdB = max;
219 }
220 }
221 if ((err = snd_mixer_selem_set_playback_dB(elem, SND_MIXER_SCHN_FRONT_LEFT, 100 * ldB, 1)) < 0) {
222 LOG_ERROR("error setting left volume: %s", snd_strerror(err));
223 }
224 if ((err = snd_mixer_selem_set_playback_dB(elem, SND_MIXER_SCHN_FRONT_RIGHT, 100 * rdB, 1)) < 0) {
225 LOG_ERROR("error setting right volume: %s", snd_strerror(err));
226 }
227 }
228
229 if ((err = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &nleft)) < 0) {
230 LOG_ERROR("error getting left vol: %s", snd_strerror(err));
231 }
232 if ((err = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &nright)) < 0) {
233 LOG_ERROR("error getting right vol: %s", snd_strerror(err));
234 }
235
236 LOG_DEBUG("%s left: %3.1fdB -> %ld right: %3.1fdB -> %ld", mixer, ldB, nleft, rdB, nright);
237
238 snd_mixer_close(handle);
239 }
240
241 void set_volume(unsigned left, unsigned right) {
242 float ldB, rdB;
243
244 if (!alsa.volume_mixer_name) {
245 LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
246 LOCK;
247 output.gainL = left;
248 output.gainR = right;
249 UNLOCK;
250 return;
251 } else {
252 LOCK;
253 output.gainL = FIXED_ONE;
254 output.gainR = FIXED_ONE;
255 UNLOCK;
256 }
257
258 // convert 16.16 fixed point to dB
259 ldB = 20 * log10( left / 65536.0F );
260 rdB = 20 * log10( right / 65536.0F );
261
262 set_mixer(output.device, alsa.volume_mixer_name, alsa.volume_mixer_index, false, ldB, rdB);
263 }
264
265 static void *alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt, ...) {
266 va_list args;
267 if ((loglevel >= lINFO && err == 0) || loglevel >= lDEBUG) {
268 fprintf(stderr, "%s ALSA %s:%d ", logtime(), function, line);
269 va_start(args, fmt);
270 vfprintf(stderr, fmt, args);
271 fprintf(stderr, "\n");
272 fflush(stderr);
273 }
274 return NULL;
275 }
276
277 static void alsa_close(void) {
278 int err;
279 if ((err = snd_pcm_close(pcmp)) < 0) {
280 LOG_INFO("snd_pcm_close error: %s", snd_strerror(err));
281 }
282 }
283
284 bool test_open(const char *device, unsigned rates[]) {
285 int err;
286 snd_pcm_t *pcm;
287 snd_pcm_hw_params_t *hw_params;
288 hw_params = (snd_pcm_hw_params_t *) alloca(snd_pcm_hw_params_sizeof());
289 memset(hw_params, 0, snd_pcm_hw_params_sizeof());
290
291 // open device
292 if ((err = snd_pcm_open(&pcm, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
293 LOG_ERROR("playback open error: %s", snd_strerror(err));
294 return false;
295 }
296
297 // get max params
298 if ((err = snd_pcm_hw_params_any(pcm, hw_params)) < 0) {
299 LOG_ERROR("hwparam init error: %s", snd_strerror(err));
300 return false;
301 }
302
303 // find supported sample rates to enable client side resampling of non supported rates
304 unsigned i, ind;
305 unsigned ref[] TEST_RATES;
306
307 for (i = 0, ind = 0; ref[i]; ++i) {
308 if (snd_pcm_hw_params_test_rate(pcm, hw_params, ref[i], 0) == 0) {
309 rates[ind++] = ref[i];
310 }
311 }
312
313 if ((err = snd_pcm_close(pcm)) < 0) {
314 LOG_ERROR("snd_pcm_close error: %s", snd_strerror(err));
315 return false;
316 }
317
318 return true;
319 }
320
321 static bool pcm_probe(const char *device) {
322 int err;
323 snd_pcm_t *pcm;
324
325 if ((err = snd_pcm_open(&pcm, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
326 return false;
327 }
328
329 if ((err = snd_pcm_close(pcm)) < 0) {
330 LOG_ERROR("snd_pcm_close error: %s", snd_strerror(err));
331 }
332
333 return true;
334 }
335
336 static int alsa_open(const char *device, unsigned sample_rate, unsigned alsa_buffer, unsigned alsa_period) {
337 int err;
338 snd_pcm_hw_params_t *hw_params;
339 snd_pcm_hw_params_alloca(&hw_params);
340
341 // close if already open
342 if (pcmp) alsa_close();
343
344 // reset params
345 alsa.rate = 0;
346 alsa.period_size = 0;
347 strcpy(alsa.device, device);
348
349 if (strlen(device) > MAX_DEVICE_LEN - 4 - 1) {
350 LOG_ERROR("device name too long: %s", device);
351 return -1;
352 }
353
354 LOG_INFO("opening device at: %u", sample_rate);
355
356 bool retry;
357 do {
358 // open device
359 if ((err = snd_pcm_open(&pcmp, alsa.device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
360 LOG_ERROR("playback open error: %s", snd_strerror(err));
361 return err;
362 }
363
364 // init params
365 memset(hw_params, 0, snd_pcm_hw_params_sizeof());
366 if ((err = snd_pcm_hw_params_any(pcmp, hw_params)) < 0) {
367 LOG_ERROR("hwparam init error: %s", snd_strerror(err));
368 return err;
369 }
370
371 // open hw: devices without resampling, if sample rate fails try plughw: with resampling
372 bool hw = !strncmp(alsa.device, "hw:", 3);
373 retry = false;
374
375 if ((err = snd_pcm_hw_params_set_rate_resample(pcmp, hw_params, !hw)) < 0) {
376 LOG_ERROR("resampling setup failed: %s", snd_strerror(err));
377 return err;
378 }
379
380 if ((err = snd_pcm_hw_params_set_rate(pcmp, hw_params, sample_rate, 0)) < 0) {
381 if (hw) {
382 strcpy(alsa.device + 4, device);
383 memcpy(alsa.device, "plug", 4);
384 LOG_INFO("reopening device %s in plug mode as %s for resampling", device, alsa.device);
385 snd_pcm_close(pcmp);
386 retry = true;
387 }
388 }
389
390 } while (retry);
391
392 // set access
393 if (!alsa.mmap || snd_pcm_hw_params_set_access(pcmp, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
394 if ((err = snd_pcm_hw_params_set_access(pcmp, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
395 LOG_ERROR("access type not available: %s", snd_strerror(err));
396 return err;
397 }
398 alsa.mmap = false;
399 }
400
401 // set the sample format
402 snd_pcm_format_t *fmt = alsa.format ? &alsa.format : (snd_pcm_format_t *)fmts;
403 do {
404 if (snd_pcm_hw_params_set_format(pcmp, hw_params, *fmt) >= 0) {
405 LOG_INFO("opened device %s using format: %s sample rate: %u mmap: %u", alsa.device, snd_pcm_format_name(*fmt), sample_rate, alsa.mmap);
406 alsa.format = *fmt;
407 break;
408 }
409 if (alsa.format) {
410 LOG_ERROR("unable to open audio device requested format: %s", snd_pcm_format_name(alsa.format));
411 return -1;
412 }
413 ++fmt;
414 if (*fmt == SND_PCM_FORMAT_UNKNOWN) {
415 LOG_ERROR("unable to open audio device with any supported format");
416 return -1;
417 }
418 } while (*fmt != SND_PCM_FORMAT_UNKNOWN);
419
420 // set the output format to be used by _scale_and_pack
421 switch(alsa.format) {
422 case SND_PCM_FORMAT_S32_LE:
423 output.format = S32_LE; break;
424 case SND_PCM_FORMAT_S24_LE:
425 output.format = S24_LE; break;
426 case SND_PCM_FORMAT_S24_3LE:
427 output.format = S24_3LE; break;
428 case SND_PCM_FORMAT_S16_LE:
429 output.format = S16_LE; break;
430 default:
431 break;
432 }
433
434 // set channels
435 if ((err = snd_pcm_hw_params_set_channels (pcmp, hw_params, 2)) < 0) {
436 LOG_ERROR("channel count not available: %s", snd_strerror(err));
437 return err;
438 }
439
440 // set period size - value of < 50 treated as period count, otherwise size in bytes
441 if (alsa_period < 50) {
442 unsigned count = alsa_period;
443 if ((err = snd_pcm_hw_params_set_periods_near(pcmp, hw_params, &count, 0)) < 0) {
444 LOG_ERROR("unable to set period count %s", snd_strerror(err));
445 return err;
446 }
447 } else {
448 snd_pcm_uframes_t size = alsa_period;
449 int dir = 0;
450 if ((err = snd_pcm_hw_params_set_period_size_near(pcmp, hw_params, &size, &dir)) < 0) {
451 LOG_ERROR("unable to set period size %s", snd_strerror(err));
452 return err;
453 }
454 }
455
456 // set buffer size - value of < 500 treated as buffer time in ms, otherwise size in bytes
457 if (alsa_buffer < 500) {
458 unsigned time = alsa_buffer * 1000;
459 int dir = 0;
460 if ((err = snd_pcm_hw_params_set_buffer_time_near(pcmp, hw_params, &time, &dir)) < 0) {
461 LOG_ERROR("unable to set buffer time %s", snd_strerror(err));
462 return err;
463 }
464 } else {
465 snd_pcm_uframes_t size = alsa_buffer;
466 if ((err = snd_pcm_hw_params_set_buffer_size_near(pcmp, hw_params, &size)) < 0) {
467 LOG_ERROR("unable to set buffer size %s", snd_strerror(err));
468 return err;
469 }
470 }
471
472 // get period_size
473 if ((err = snd_pcm_hw_params_get_period_size(hw_params, &alsa.period_size, 0)) < 0) {
474 LOG_ERROR("unable to get period size: %s", snd_strerror(err));
475 return err;
476 }
477
478 // get buffer_size
479 if ((err = snd_pcm_hw_params_get_buffer_size(hw_params, &alsa.buffer_size)) < 0) {
480 LOG_ERROR("unable to get buffer size: %s", snd_strerror(err));
481 return err;
482 }
483
484 LOG_INFO("buffer: %u period: %u -> buffer size: %u period size: %u", alsa_buffer, alsa_period, alsa.buffer_size, alsa.period_size);
485
486 // ensure we have two buffer sizes of samples before starting output
487 output.start_frames = alsa.buffer_size * 2;
488
489 // create an intermediate buffer for non mmap case for all but NATIVE_FORMAT
490 // this is used to pack samples into the output format before calling writei
491 if (!alsa.mmap && !alsa.write_buf && alsa.format != NATIVE_FORMAT) {
492 alsa.write_buf = malloc(alsa.buffer_size * BYTES_PER_FRAME);
493 if (!alsa.write_buf) {
494 LOG_ERROR("unable to malloc write_buf");
495 return -1;
496 }
497 }
498
499 // set params
500 if ((err = snd_pcm_hw_params(pcmp, hw_params)) < 0) {
501 LOG_ERROR("unable to set hw params: %s", snd_strerror(err));
502 return err;
503 }
504
505 // dump info
506 if (loglevel == lSDEBUG) {
507 static snd_output_t *debug_output;
508 snd_output_stdio_attach(&debug_output, stderr, 0);
509 snd_pcm_dump(pcmp, debug_output);
510 }
511
512 // this indicates we have opened the device ok
513 alsa.rate = sample_rate;
514
515 return 0;
516 }
517
518 static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
519 s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) {
520
521 const snd_pcm_channel_area_t *areas;
522 snd_pcm_uframes_t offset;
523 void *outputptr;
524 s32_t *inputptr;
525 int err;
526
527 if (alsa.mmap) {
528 snd_pcm_uframes_t alsa_frames = (snd_pcm_uframes_t)out_frames;
529
530 snd_pcm_avail_update(pcmp);
531
532 if ((err = snd_pcm_mmap_begin(pcmp, &areas, &offset, &alsa_frames)) < 0) {
533 LOG_WARN("error from mmap_begin: %s", snd_strerror(err));
534 return -1;
535 }
536
537 out_frames = (frames_t)alsa_frames;
538 }
539
540 if (!silence) {
541 // applying cross fade is delayed until this point as mmap_begin can change out_frames
542 if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
543 _apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
544 }
545 }
546
547 inputptr = (s32_t *) (silence ? silencebuf : outputbuf->readp);
548
549 IF_DSD(
550 if (output.dop) {
551 if (silence) {
552 inputptr = (s32_t *) silencebuf_dop;
553 }
554 update_dop((u32_t *) inputptr, out_frames, output.invert && !silence);
555 }
556 )
557
558 if (alsa.mmap || alsa.format != NATIVE_FORMAT) {
559
560 outputptr = alsa.mmap ? (areas[0].addr + (areas[0].first + offset * areas[0].step) / 8) : alsa.write_buf;
561
562 _scale_and_pack_frames(outputptr, inputptr, out_frames, gainL, gainR, output.format);
563
564 } else {
565
566 outputptr = (void *)inputptr;
567
568 if (!silence) {
569
570 if (gainL != FIXED_ONE || gainR!= FIXED_ONE) {
571 _apply_gain(outputbuf, out_frames, gainL, gainR);
572 }
573 }
574 }
575
576 if (alsa.mmap) {
577
578 snd_pcm_sframes_t w = snd_pcm_mmap_commit(pcmp, offset, out_frames);
579 if (w < 0 || w != out_frames) {
580 LOG_WARN("mmap_commit error");
581 return -1;
582 }
583
584 } else {
585
586 snd_pcm_sframes_t w = snd_pcm_writei(pcmp, outputptr, out_frames);
587 if (w < 0) {
588 //if (w != -EAGAIN && ((err = snd_pcm_recover(pcmp, w, 1)) < 0)) {
589 if (((err = snd_pcm_recover(pcmp, w, 1)) < 0)) {
590 static unsigned recover_count = 0;
591 LOG_WARN("recover failed: %s [%u]", snd_strerror(err), ++recover_count);
592 if (recover_count >= 10) {
593 recover_count = 0;
594 alsa_close();
595 pcmp = NULL;
596 }
597 }
598 return -1;
599 } else {
600 if (w != out_frames) {
601 LOG_WARN("writei only wrote %u of %u", w, out_frames);
602 }
603 out_frames = w;
604 }
605 }
606
607 return (int)out_frames;
608 }
609
610 static void *output_thread(void *arg) {
611 bool start = true;
612 bool output_off = (output.state == OUTPUT_OFF);
613 bool probe_device = (arg != NULL);
614 int err;
615
616 while (running) {
617
618 // disabled output - player is off
619 while (output_off) {
620 usleep(100000);
621 LOCK;
622 output_off = (output.state == OUTPUT_OFF);
623 UNLOCK;
624 if (!running) return 0;
625 }
626
627 // wait until device returns - to allow usb audio devices to be turned off
628 if (probe_device) {
629 while (!pcm_probe(output.device)) {
630 LOG_DEBUG("waiting for device %s to return", output.device);
631 sleep(5);
632 }
633 probe_device = false;
634 }
635
636 if (!pcmp || alsa.rate != output.current_sample_rate) {
637 LOG_INFO("open output device: %s", output.device);
638 LOCK;
639
640 // FIXME - some alsa hardware requires opening twice for a new sample rate to work
641 // this is a workaround which should be removed
642 if (alsa.reopen) {
643 alsa_open(output.device, output.current_sample_rate, output.buffer, output.period);
644 }
645
646 if (!!alsa_open(output.device, output.current_sample_rate, output.buffer, output.period)) {
647 output.error_opening = true;
648 UNLOCK;
649 sleep(5);
650 continue;
651 }
652 output.error_opening = false;
653 start = true;
654 UNLOCK;
655 }
656
657 snd_pcm_state_t state = snd_pcm_state(pcmp);
658
659 if (state == SND_PCM_STATE_XRUN) {
660 LOG_INFO("XRUN");
661 if ((err = snd_pcm_recover(pcmp, -EPIPE, 1)) < 0) {
662 LOG_INFO("XRUN recover failed: %s", snd_strerror(err));
663 }
664 start = true;
665 continue;
666 } else if (state == SND_PCM_STATE_SUSPENDED) {
667 if ((err = snd_pcm_recover(pcmp, -ESTRPIPE, 1)) < 0) {
668 LOG_INFO("SUSPEND recover failed: %s", snd_strerror(err));
669 }
670 } else if (state == SND_PCM_STATE_DISCONNECTED) {
671 LOG_INFO("Device %s no longer available", output.device);
672 alsa_close();
673 pcmp = NULL;
674 probe_device = true;
675 continue;
676 }
677
678 snd_pcm_sframes_t avail = snd_pcm_avail_update(pcmp);
679
680 if (avail < 0) {
681 if ((err = snd_pcm_recover(pcmp, avail, 1)) < 0) {
682 if (err == -ENODEV) {
683 LOG_INFO("Device %s no longer available", output.device);
684 alsa_close();
685 pcmp = NULL;
686 probe_device = true;
687 continue;
688 }
689 LOG_WARN("recover failed: %s", snd_strerror(err));
690 }
691 start = true;
692 continue;
693 }
694
695 if (avail < alsa.period_size) {
696 if (start) {
697 if (alsa.mmap && ((err = snd_pcm_start(pcmp)) < 0)) {
698 if ((err = snd_pcm_recover(pcmp, err, 1)) < 0) {
699 if (err == -ENODEV) {
700 LOG_INFO("Device %s no longer available", output.device);
701 alsa_close();
702 pcmp = NULL;
703 probe_device = true;
704 continue;
705 }
706 LOG_INFO("start error: %s", snd_strerror(err));
707 usleep(10000);
708 }
709 } else {
710 start = false;
711 }
712 } else {
713 if ((err = snd_pcm_wait(pcmp, 1000)) < 0) {
714 if ((err = snd_pcm_recover(pcmp, err, 1)) < 0) {
715 LOG_INFO("pcm wait error: %s", snd_strerror(err));
716 }
717 start = true;
718 }
719 }
720 continue;
721 }
722
723 // restrict avail to within sensible limits as alsa drivers can return erroneous large values
724 // in writei mode restrict to period_size due to size of write_buf
725 if (alsa.mmap) {
726 avail = min(avail, alsa.buffer_size);
727 } else {
728 avail = min(avail, alsa.period_size);
729 }
730
731 // avoid spinning in cases where wait returns but no bytes available (seen with pulse audio)
732 if (avail == 0) {
733 LOG_SDEBUG("avail 0 - sleeping");
734 usleep(10000);
735 continue;
736 }
737
738 LOCK;
739
740 // turn off if requested
741 if (output.state == OUTPUT_OFF) {
742 UNLOCK;
743 LOG_INFO("disabling output");
744 alsa_close();
745 pcmp = NULL;
746 output_off = true;
747 vis_stop();
748 continue;
749 }
750
751 // measure output delay
752 snd_pcm_sframes_t delay;
753 if ((err = snd_pcm_delay(pcmp, &delay)) < 0) {
754 if (err == -EPIPE) {
755 // EPIPE indicates underrun - attempt to recover
756 UNLOCK;
757 continue;
758 } else if (err == -EIO) {
759 // EIO can occur with non existant pulse server
760 UNLOCK;
761 LOG_SDEBUG("snd_pcm_delay returns: EIO - sleeping");
762 usleep(100000);
763 continue;
764 } else {
765 LOG_DEBUG("snd_pcm_delay returns: %d", err);
766 }
767 } else {
768 output.device_frames = delay;
769 output.updated = gettime_ms();
770 output.frames_played_dmp = output.frames_played;
771 }
772
773 // process frames
774 frames_t wrote = _output_frames(avail);
775
776 UNLOCK;
777
778 // some output devices such as alsa null refuse any data, avoid spinning
779 if (!wrote) {
780 LOG_SDEBUG("wrote 0 - sleeping");
781 usleep(10000);
782 }
783 }
784
785 return 0;
786 }
787
788 static pthread_t thread;
789
790 void output_init_alsa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[],
791 unsigned rate_delay, unsigned rt_priority, unsigned idle, char *volume_mixer, bool mixer_unmute) {
792
793 unsigned alsa_buffer = ALSA_BUFFER_TIME;
794 unsigned alsa_period = ALSA_PERIOD_COUNT;
795 char *alsa_sample_fmt = NULL;
796 bool alsa_mmap = true;
797 bool alsa_reopen = false;
798
799 char *volume_mixer_name = next_param(volume_mixer, ',');
800 char *volume_mixer_index = next_param(NULL, ',');
801
802 char *t = next_param(params, ':');
803 char *c = next_param(NULL, ':');
804 char *s = next_param(NULL, ':');
805 char *m = next_param(NULL, ':');
806 char *r = next_param(NULL, ':');
807
808 if (t) alsa_buffer = atoi(t);
809 if (c) alsa_period = atoi(c);
810 if (s) alsa_sample_fmt = s;
811 if (m) alsa_mmap = atoi(m);
812 if (r) alsa_reopen = atoi(r);
813
814 loglevel = level;
815
816 LOG_INFO("init output");
817
818 memset(&output, 0, sizeof(output));
819
820 alsa.mmap = alsa_mmap;
821 alsa.write_buf = NULL;
822 alsa.format = 0;
823 alsa.reopen = alsa_reopen;
824
825 if (!mixer_unmute) {
826 alsa.volume_mixer_name = volume_mixer_name;
827 alsa.volume_mixer_index = volume_mixer_index ? atoi(volume_mixer_index) : 0;
828 }
829
830 output.format = 0;
831 output.buffer = alsa_buffer;
832 output.period = alsa_period;
833 output.start_frames = 0;
834 output.write_cb = &_write_frames;
835 output.rate_delay = rate_delay;
836
837 if (alsa_sample_fmt) {
838 if (!strcmp(alsa_sample_fmt, "32")) alsa.format = SND_PCM_FORMAT_S32_LE;
839 if (!strcmp(alsa_sample_fmt, "24")) alsa.format = SND_PCM_FORMAT_S24_LE;
840 if (!strcmp(alsa_sample_fmt, "24_3")) alsa.format = SND_PCM_FORMAT_S24_3LE;
841 if (!strcmp(alsa_sample_fmt, "16")) alsa.format = SND_PCM_FORMAT_S16_LE;
842 }
843
844 LOG_INFO("requested alsa_buffer: %u alsa_period: %u format: %s mmap: %u", output.buffer, output.period,
845 alsa_sample_fmt ? alsa_sample_fmt : "any", alsa.mmap);
846
847 snd_lib_error_set_handler((snd_lib_error_handler_t)alsa_error_handler);
848
849 output_init_common(level, device, output_buf_size, rates, idle);
850
851 if (mixer_unmute && volume_mixer_name) {
852 set_mixer(output.device, volume_mixer_name, volume_mixer_index ? atoi(volume_mixer_index) : 0, true, 0, 0);
853 }
854
855 #if LINUX
856 // RT linux - aim to avoid pagefaults by locking memory:
857 // https://rt.wiki.kernel.org/index.php/Threaded_RT-application_with_memory_locking_and_stack_handling_example
858 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
859 LOG_INFO("unable to lock memory: %s", strerror(errno));
860 } else {
861 LOG_INFO("memory locked");
862 }
863
864 mallopt(M_TRIM_THRESHOLD, -1);
865 mallopt(M_MMAP_MAX, 0);
866
867 touch_memory(silencebuf, MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
868 touch_memory(outputbuf->buf, outputbuf->size);
869 #endif
870
871 // start output thread
872 pthread_attr_t attr;
873 pthread_attr_init(&attr);
874 pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + OUTPUT_THREAD_STACK_SIZE);
875 pthread_create(&thread, &attr, output_thread, rates[0] ? "probe" : NULL);
876 pthread_attr_destroy(&attr);
877
878 // try to set this thread to real-time scheduler class, only works as root or if user has permission
879 struct sched_param param;
880 param.sched_priority = rt_priority;
881 if (pthread_setschedparam(thread, SCHED_FIFO, &param) != 0) {
882 LOG_DEBUG("unable to set output sched fifo: %s", strerror(errno));
883 } else {
884 LOG_DEBUG("set output sched fifo rt: %u", param.sched_priority);
885 }
886 }
887
888 void output_close_alsa(void) {
889 LOG_INFO("close output");
890
891 LOCK;
892 running = false;
893 UNLOCK;
894
895 pthread_join(thread, NULL);
896
897 if (alsa.write_buf) free(alsa.write_buf);
898
899 output_close_common();
900 }
901
902 #endif // ALSA
903
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // Portaudio output
21
22 #include "squeezelite.h"
23
24 #if PORTAUDIO
25
26 #include <portaudio.h>
27 #if OSX
28 #include <pa_mac_core.h>
29 #endif
30
31 // ouput device
32 static struct {
33 unsigned rate;
34 PaStream *stream;
35 } pa;
36
37 static log_level loglevel;
38
39 static bool running = true;
40
41 extern struct outputstate output;
42 extern struct buffer *outputbuf;
43
44 #define LOCK mutex_lock(outputbuf->mutex)
45 #define UNLOCK mutex_unlock(outputbuf->mutex)
46
47 extern u8_t *silencebuf;
48 #if DSD
49 extern u8_t *silencebuf_dop;
50 #endif
51
52 void list_devices(void) {
53 PaError err;
54 int i;
55
56 if ((err = Pa_Initialize()) != paNoError) {
57 LOG_WARN("error initialising port audio: %s", Pa_GetErrorText(err));
58 return;
59 }
60
61 printf("Output devices:\n");
62 for (i = 0; i < Pa_GetDeviceCount(); ++i) {
63 if (Pa_GetDeviceInfo(i)->maxOutputChannels) {
64 printf(" %i - %s [%s]\n", i, Pa_GetDeviceInfo(i)->name, Pa_GetHostApiInfo(Pa_GetDeviceInfo(i)->hostApi)->name);
65 }
66 }
67 printf("\n");
68
69 if ((err = Pa_Terminate()) != paNoError) {
70 LOG_WARN("error closing port audio: %s", Pa_GetErrorText(err));
71 }
72 }
73
74 void set_volume(unsigned left, unsigned right) {
75 LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
76 LOCK;
77 output.gainL = left;
78 output.gainR = right;
79 UNLOCK;
80 }
81
82 static int pa_device_id(const char *device) {
83 int len = strlen(device);
84 int i;
85
86 if (!strncmp(device, "default", 7)) {
87 return Pa_GetDefaultOutputDevice();
88 }
89 if (len >= 1 && len <= 2 && device[0] >= '0' && device[0] <= '9') {
90 return atoi(device);
91 }
92
93 #define DEVICE_ID_MAXLEN 256
94 for (i = 0; i < Pa_GetDeviceCount(); ++i) {
95 char tmp[DEVICE_ID_MAXLEN];
96 snprintf(tmp, DEVICE_ID_MAXLEN, "%s [%s]", Pa_GetDeviceInfo(i)->name, Pa_GetHostApiInfo(Pa_GetDeviceInfo(i)->hostApi)->name);
97 if (!strncmp(tmp, device, len)) {
98 return i;
99 }
100 }
101
102 return -1;
103 }
104
105 static int pa_callback(const void *pa_input, void *pa_output, unsigned long pa_frames_wanted,
106 const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData);
107
108 bool test_open(const char *device, unsigned rates[]) {
109 PaStreamParameters outputParameters;
110 PaError err;
111 unsigned ref[] TEST_RATES;
112 int device_id, i, ind;
113
114 if ((device_id = pa_device_id(device)) == -1) {
115 LOG_INFO("device %s not found", device);
116 return false;
117 }
118
119 outputParameters.device = device_id;
120 outputParameters.channelCount = 2;
121 outputParameters.sampleFormat = paInt32;
122 outputParameters.suggestedLatency =
123 output.latency ? (double)output.latency/(double)1000 : Pa_GetDeviceInfo(outputParameters.device)->defaultHighOutputLatency;
124 outputParameters.hostApiSpecificStreamInfo = NULL;
125
126 // check supported sample rates
127 // Note use Pa_OpenStream as it appears more reliable than Pa_IsFormatSupported on some windows apis
128 for (i = 0, ind = 0; ref[i]; ++i) {
129 err = Pa_OpenStream(&pa.stream, NULL, &outputParameters, (double)ref[i], paFramesPerBufferUnspecified, paNoFlag,
130 pa_callback, NULL);
131 if (err == paNoError) {
132 Pa_CloseStream(pa.stream);
133 rates[ind++] = ref[i];
134 }
135 }
136
137 if (!rates[0]) {
138 LOG_WARN("no available rate found");
139 return false;
140 }
141
142 pa.stream = NULL;
143 return true;
144 }
145
146 static void pa_stream_finished(void *userdata) {
147 if (running) {
148 LOG_INFO("stream finished");
149 LOCK;
150 output.pa_reopen = true;
151 wake_controller();
152 UNLOCK;
153 }
154 }
155
156 static thread_type monitor_thread;
157 bool monitor_thread_running = false;
158
159 static void *pa_monitor() {
160 bool output_off;
161
162 LOCK;
163
164 if (monitor_thread_running) {
165 LOG_DEBUG("monitor thread already running");
166 UNLOCK;
167 return 0;
168 }
169
170 LOG_DEBUG("start monitor thread");
171
172 monitor_thread_running = true;
173 output_off = (output.state == OUTPUT_OFF);
174
175 while (monitor_thread_running) {
176 if (output_off) {
177 if (output.state != OUTPUT_OFF) {
178 LOG_INFO("output on");
179 break;
180 }
181 } else {
182 // this is a hack to partially support hot plugging of devices
183 // we rely on terminating and reinitalising PA to get an updated list of devices and use name for output.device
184 LOG_INFO("probing device %s", output.device);
185 Pa_Terminate();
186 Pa_Initialize();
187 pa.stream = NULL;
188 if (pa_device_id(output.device) != -1) {
189 LOG_INFO("device reopen");
190 break;
191 }
192 }
193
194 UNLOCK;
195 sleep(output_off ? 1 : 5);
196 LOCK;
197 }
198
199 LOG_DEBUG("end monitor thread");
200
201 monitor_thread_running = false;
202 pa.stream = NULL;
203
204 _pa_open();
205
206 UNLOCK;
207
208 return 0;
209 }
210
211 void _pa_open(void) {
212 PaStreamParameters outputParameters;
213 PaError err = paNoError;
214 int device_id;
215
216 if (pa.stream) {
217 if ((err = Pa_CloseStream(pa.stream)) != paNoError) {
218 LOG_WARN("error closing stream: %s", Pa_GetErrorText(err));
219 }
220 }
221
222 if (output.state == OUTPUT_OFF) {
223 // we get called when transitioning to OUTPUT_OFF to create the probe thread
224 // set err to avoid opening device and logging messages
225 err = 1;
226
227 } else if ((device_id = pa_device_id(output.device)) == -1) {
228 LOG_INFO("device %s not found", output.device);
229 err = 1;
230
231 } else {
232
233 outputParameters.device = device_id;
234 outputParameters.channelCount = 2;
235 outputParameters.sampleFormat = paInt32;
236 outputParameters.suggestedLatency =
237 output.latency ? (double)output.latency/(double)1000 : Pa_GetDeviceInfo(outputParameters.device)->defaultHighOutputLatency;
238 outputParameters.hostApiSpecificStreamInfo = NULL;
239
240 #if OSX
241 // enable pro mode which aims to avoid resampling if possible
242 // see http://code.google.com/p/squeezelite/issues/detail?id=11 & http://code.google.com/p/squeezelite/issues/detail?id=37
243 // command line controls osx_playnice which is -1 if not specified, 0 or 1 - choose playnice if -1 or 1
244 PaMacCoreStreamInfo macInfo;
245 unsigned long streamInfoFlags;
246 if (output.osx_playnice) {
247 LOG_INFO("opening device in PlayNice mode");
248 streamInfoFlags = paMacCorePlayNice;
249 } else {
250 LOG_INFO("opening device in Pro mode");
251 streamInfoFlags = paMacCorePro;
252 }
253 PaMacCore_SetupStreamInfo(&macInfo, streamInfoFlags);
254 outputParameters.hostApiSpecificStreamInfo = &macInfo;
255 #endif
256 }
257
258 if (!err &&
259 (err = Pa_OpenStream(&pa.stream, NULL, &outputParameters, (double)output.current_sample_rate, paFramesPerBufferUnspecified,
260 paPrimeOutputBuffersUsingStreamCallback | paDitherOff, pa_callback, NULL)) != paNoError) {
261 LOG_WARN("error opening device %i - %s : %s", outputParameters.device, Pa_GetDeviceInfo(outputParameters.device)->name,
262 Pa_GetErrorText(err));
263 }
264
265 if (!err) {
266 LOG_INFO("opened device %i - %s at %u latency %u ms", outputParameters.device, Pa_GetDeviceInfo(outputParameters.device)->name,
267 (unsigned int)Pa_GetStreamInfo(pa.stream)->sampleRate, (unsigned int)(Pa_GetStreamInfo(pa.stream)->outputLatency * 1000));
268
269 pa.rate = output.current_sample_rate;
270
271 if ((err = Pa_SetStreamFinishedCallback(pa.stream, pa_stream_finished)) != paNoError) {
272 LOG_WARN("error setting finish callback: %s", Pa_GetErrorText(err));
273 }
274
275 UNLOCK; // StartStream can call pa_callback in a sychronised thread on freebsd, remove lock while it is called
276
277 if ((err = Pa_StartStream(pa.stream)) != paNoError) {
278 LOG_WARN("error starting stream: %s", Pa_GetErrorText(err));
279 }
280
281 LOCK;
282 }
283
284 if (err && !monitor_thread_running) {
285 vis_stop();
286
287 // create a thread to check for output state change or device return
288 #if LINUX || OSX || FREEBSD
289 pthread_create(&monitor_thread, NULL, pa_monitor, NULL);
290 #endif
291 #if WIN
292 monitor_thread = CreateThread(NULL, OUTPUT_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&pa_monitor, NULL, 0, NULL);
293 #endif
294 }
295
296 output.error_opening = !!err;
297 }
298
299 static u8_t *optr;
300
301 static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
302 s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) {
303
304 if (!silence) {
305
306 if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
307 _apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
308 }
309
310 if (gainL != FIXED_ONE || gainR!= FIXED_ONE) {
311 _apply_gain(outputbuf, out_frames, gainL, gainR);
312 }
313
314 IF_DSD(
315 if (output.dop) {
316 update_dop((u32_t *) outputbuf->readp, out_frames, output.invert);
317 }
318 )
319
320 memcpy(optr, outputbuf->readp, out_frames * BYTES_PER_FRAME);
321
322 } else {
323
324 u8_t *buf = silencebuf;
325
326 IF_DSD(
327 if (output.dop) {
328 buf = silencebuf_dop;
329 update_dop((u32_t *) buf, out_frames, false); // don't invert silence
330 }
331 )
332
333 memcpy(optr, buf, out_frames * BYTES_PER_FRAME);
334 }
335
336 optr += out_frames * BYTES_PER_FRAME;
337
338 return (int)out_frames;
339 }
340
341 static int pa_callback(const void *pa_input, void *pa_output, unsigned long pa_frames_wanted,
342 const PaStreamCallbackTimeInfo *time_info, PaStreamCallbackFlags statusFlags, void *userData) {
343 int ret;
344 double stream_time;
345 frames_t frames;
346
347 optr = (u8_t *)pa_output;
348
349 LOCK;
350
351 stream_time = Pa_GetStreamTime(pa.stream);
352
353 if (time_info->outputBufferDacTime > stream_time) {
354 // workaround for wdm-ks which can return outputBufferDacTime with a different epoch
355 output.device_frames = (unsigned)((time_info->outputBufferDacTime - stream_time) * output.current_sample_rate);
356 } else {
357 output.device_frames = 0;
358 }
359
360 output.updated = gettime_ms();
361 output.frames_played_dmp = output.frames_played;
362
363 do {
364 frames = _output_frames(pa_frames_wanted);
365 pa_frames_wanted -= frames;
366 } while (pa_frames_wanted > 0 && frames != 0);
367
368 if (pa_frames_wanted > 0) {
369 LOG_DEBUG("pad with silence");
370 memset(optr, 0, pa_frames_wanted * BYTES_PER_FRAME);
371 }
372
373 if (output.state == OUTPUT_OFF) {
374 LOG_INFO("output off");
375 ret = paComplete;
376 } else if (pa.rate != output.current_sample_rate) {
377 ret = paComplete;
378 } else {
379 ret = paContinue;
380 }
381
382 UNLOCK;
383
384 return ret;
385 }
386
387 void output_init_pa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay,
388 unsigned idle) {
389 PaError err;
390 unsigned latency = 0;
391 int osx_playnice = -1;
392
393 char *l = next_param(params, ':');
394 char *p = next_param(NULL, ':');
395
396 if (l) latency = (unsigned)atoi(l);
397 if (p) osx_playnice = atoi(p);
398
399 loglevel = level;
400
401 LOG_INFO("init output");
402
403 memset(&output, 0, sizeof(output));
404
405 output.latency = latency;
406 output.osx_playnice = osx_playnice;
407 output.format = 0;
408 output.start_frames = 0;
409 output.write_cb = &_write_frames;
410 output.rate_delay = rate_delay;
411 pa.stream = NULL;
412
413 LOG_INFO("requested latency: %u", output.latency);
414
415 if ((err = Pa_Initialize()) != paNoError) {
416 LOG_WARN("error initialising port audio: %s", Pa_GetErrorText(err));
417 exit(0);
418 }
419
420 output_init_common(level, device, output_buf_size, rates, idle);
421
422 LOCK;
423
424 _pa_open();
425
426 UNLOCK;
427 }
428
429 void output_close_pa(void) {
430 PaError err;
431
432 LOG_INFO("close output");
433
434 LOCK;
435
436 running = false;
437 monitor_thread_running = false;
438
439 if (pa.stream) {
440 if ((err = Pa_AbortStream(pa.stream)) != paNoError) {
441 LOG_WARN("error closing stream: %s", Pa_GetErrorText(err));
442 }
443 }
444
445 if ((err = Pa_Terminate()) != paNoError) {
446 LOG_WARN("error closing port audio: %s", Pa_GetErrorText(err));
447 }
448
449 UNLOCK;
450
451 output_close_common();
452 }
453
454 #endif // PORTAUDIO
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // Scale and pack functions
21
22 #include "squeezelite.h"
23
24 #define MAX_SCALESAMPLE 0x7fffffffffffLL
25 #define MIN_SCALESAMPLE -MAX_SCALESAMPLE
26
27 // inlining these on windows prevents them being linkable...
28 #if !WIN
29 inline
30 #endif
31 s32_t gain(s32_t gain, s32_t sample) {
32 s64_t res = (s64_t)gain * (s64_t)sample;
33 if (res > MAX_SCALESAMPLE) res = MAX_SCALESAMPLE;
34 if (res < MIN_SCALESAMPLE) res = MIN_SCALESAMPLE;
35 return (s32_t) (res >> 16);
36 }
37 #if !WIN
38 inline
39 #endif
40 s32_t to_gain(float f) {
41 return (s32_t)(f * 65536.0F);
42 }
43
44 void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, output_format format) {
45 switch(format) {
46 case S16_LE:
47 {
48 u32_t *optr = (u32_t *)(void *)outputptr;
49 #if SL_LITTLE_ENDIAN
50 if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
51 while (cnt--) {
52 *(optr++) = (*(inputptr) >> 16 & 0x0000ffff) | (*(inputptr + 1) & 0xffff0000);
53 inputptr += 2;
54 }
55 } else {
56 while (cnt--) {
57 *(optr++) = (gain(gainL, *(inputptr)) >> 16 & 0x0000ffff) | (gain(gainR, *(inputptr+1)) & 0xffff0000);
58 inputptr += 2;
59 }
60 }
61 #else
62 if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
63 while (cnt--) {
64 s32_t lsample = *(inputptr++);
65 s32_t rsample = *(inputptr++);
66 *(optr++) =
67 (lsample & 0x00ff0000) << 8 | (lsample & 0xff000000) >> 8 |
68 (rsample & 0x00ff0000) >> 8 | (rsample & 0xff000000) >> 24;
69 }
70 } else {
71 while (cnt--) {
72 s32_t lsample = gain(gainL, *(inputptr++));
73 s32_t rsample = gain(gainR, *(inputptr++));
74 *(optr++) =
75 (lsample & 0x00ff0000) << 8 | (lsample & 0xff000000) >> 8 |
76 (rsample & 0x00ff0000) >> 8 | (rsample & 0xff000000) >> 24;
77 }
78 }
79 #endif
80 }
81 break;
82 case S24_LE:
83 {
84 u32_t *optr = (u32_t *)(void *)outputptr;
85 #if SL_LITTLE_ENDIAN
86 if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
87 while (cnt--) {
88 *(optr++) = *(inputptr++) >> 8;
89 *(optr++) = *(inputptr++) >> 8;
90 }
91 } else {
92 while (cnt--) {
93 *(optr++) = gain(gainL, *(inputptr++)) >> 8;
94 *(optr++) = gain(gainR, *(inputptr++)) >> 8;
95 }
96 }
97 #else
98 if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
99 while (cnt--) {
100 s32_t lsample = *(inputptr++);
101 s32_t rsample = *(inputptr++);
102 *(optr++) =
103 (lsample & 0xff000000) >> 16 | (lsample & 0x00ff0000) | (lsample & 0x0000ff00 << 16);
104 *(optr++) =
105 (rsample & 0xff000000) >> 16 | (rsample & 0x00ff0000) | (rsample & 0x0000ff00 << 16);
106 }
107 } else {
108 while (cnt--) {
109 s32_t lsample = gain(gainL, *(inputptr++));
110 s32_t rsample = gain(gainR, *(inputptr++));
111 *(optr++) =
112 (lsample & 0xff000000) >> 16 | (lsample & 0x00ff0000) | (lsample & 0x0000ff00 << 16);
113 *(optr++) =
114 (rsample & 0xff000000) >> 16 | (rsample & 0x00ff0000) | (rsample & 0x0000ff00 << 16);
115 }
116 }
117 #endif
118 }
119 break;
120 case S24_3LE:
121 {
122 u8_t *optr = (u8_t *)(void *)outputptr;
123 if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
124 while (cnt) {
125 // attempt to do 32 bit memory accesses - move 2 frames at once: 16 bytes -> 12 bytes
126 // falls through to exception case when not aligned or if less than 2 frames to move
127 if (((uintptr_t)optr & 0x3) == 0 && cnt >= 2) {
128 u32_t *o_ptr = (u32_t *)(void *)optr;
129 while (cnt >= 2) {
130 s32_t l1 = *(inputptr++); s32_t r1 = *(inputptr++);
131 s32_t l2 = *(inputptr++); s32_t r2 = *(inputptr++);
132 #if SL_LITTLE_ENDIAN
133 *(o_ptr++) = (l1 & 0xffffff00) >> 8 | (r1 & 0x0000ff00) << 16;
134 *(o_ptr++) = (r1 & 0xffff0000) >> 16 | (l2 & 0x00ffff00) << 8;
135 *(o_ptr++) = (l2 & 0xff000000) >> 24 | (r2 & 0xffffff00);
136 #else
137 *(o_ptr++) = (l1 & 0x0000ff00) << 16 | (l1 & 0x00ff0000) | (l1 & 0xff000000) >> 16 |
138 (r1 & 0x0000ff00) >> 8;
139 *(o_ptr++) = (r1 & 0x00ff0000) << 8 | (r1 & 0xff000000) >> 8 | (l2 & 0x0000ff00) |
140 (l2 & 0x00ff0000) >> 16;
141 *(o_ptr++) = (l2 & 0xff000000) | (r2 & 0x0000ff00) << 8 | (r2 & 0x00ff0000) >> 8 |
142 (r2 & 0xff000000) >> 24;
143 #endif
144 optr += 12;
145 cnt -= 2;
146 }
147 } else {
148 s32_t lsample = *(inputptr++);
149 s32_t rsample = *(inputptr++);
150 *(optr++) = (lsample & 0x0000ff00) >> 8;
151 *(optr++) = (lsample & 0x00ff0000) >> 16;
152 *(optr++) = (lsample & 0xff000000) >> 24;
153 *(optr++) = (rsample & 0x0000ff00) >> 8;
154 *(optr++) = (rsample & 0x00ff0000) >> 16;
155 *(optr++) = (rsample & 0xff000000) >> 24;
156 cnt--;
157 }
158 }
159 } else {
160 while (cnt) {
161 // attempt to do 32 bit memory accesses - move 2 frames at once: 16 bytes -> 12 bytes
162 // falls through to exception case when not aligned or if less than 2 frames to move
163 if (((uintptr_t)optr & 0x3) == 0 && cnt >= 2) {
164 u32_t *o_ptr = (u32_t *)(void *)optr;
165 while (cnt >= 2) {
166 s32_t l1 = gain(gainL, *(inputptr++)); s32_t r1 = gain(gainR, *(inputptr++));
167 s32_t l2 = gain(gainL, *(inputptr++)); s32_t r2 = gain(gainR, *(inputptr++));
168 #if SL_LITTLE_ENDIAN
169 *(o_ptr++) = (l1 & 0xffffff00) >> 8 | (r1 & 0x0000ff00) << 16;
170 *(o_ptr++) = (r1 & 0xffff0000) >> 16 | (l2 & 0x00ffff00) << 8;
171 *(o_ptr++) = (l2 & 0xff000000) >> 24 | (r2 & 0xffffff00);
172 #else
173 *(o_ptr++) = (l1 & 0x0000ff00) << 16 | (l1 & 0x00ff0000) | (l1 & 0xff000000) >> 16 |
174 (r1 & 0x0000ff00) >> 8;
175 *(o_ptr++) = (r1 & 0x00ff0000) << 8 | (r1 & 0xff000000) >> 8 | (l2 & 0x0000ff00) |
176 (l2 & 0x00ff0000) >> 16;
177 *(o_ptr++) = (l2 & 0xff000000) | (r2 & 0x0000ff00) << 8 | (r2 & 0x00ff0000) >> 8 |
178 (r2 & 0xff000000) >> 24;
179 #endif
180 optr += 12;
181 cnt -= 2;
182 }
183 } else {
184 s32_t lsample = gain(gainL, *(inputptr++));
185 s32_t rsample = gain(gainR, *(inputptr++));
186 *(optr++) = (lsample & 0x0000ff00) >> 8;
187 *(optr++) = (lsample & 0x00ff0000) >> 16;
188 *(optr++) = (lsample & 0xff000000) >> 24;
189 *(optr++) = (rsample & 0x0000ff00) >> 8;
190 *(optr++) = (rsample & 0x00ff0000) >> 16;
191 *(optr++) = (rsample & 0xff000000) >> 24;
192 cnt--;
193 }
194 }
195 }
196 }
197 break;
198 case S32_LE:
199 {
200 u32_t *optr = (u32_t *)(void *)outputptr;
201 #if SL_LITTLE_ENDIAN
202 if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
203 memcpy(outputptr, inputptr, cnt * BYTES_PER_FRAME);
204 } else {
205 while (cnt--) {
206 *(optr++) = gain(gainL, *(inputptr++));
207 *(optr++) = gain(gainR, *(inputptr++));
208 }
209 }
210 #else
211 if (gainL == FIXED_ONE && gainR == FIXED_ONE) {
212 while (cnt--) {
213 s32_t lsample = *(inputptr++);
214 s32_t rsample = *(inputptr++);
215 *(optr++) =
216 (lsample & 0xff000000) >> 24 | (lsample & 0x00ff0000) >> 8 |
217 (lsample & 0x0000ff00) << 8 | (lsample & 0x000000ff) << 24;
218 *(optr++) =
219 (rsample & 0xff000000) >> 24 | (rsample & 0x00ff0000) >> 8 |
220 (rsample & 0x0000ff00) << 8 | (rsample & 0x000000ff) << 24;
221 }
222 } else {
223 while (cnt--) {
224 s32_t lsample = gain(gainL, *(inputptr++));
225 s32_t rsample = gain(gainR, *(inputptr++));
226 *(optr++) =
227 (lsample & 0xff000000) >> 24 | (lsample & 0x00ff0000) >> 8 |
228 (lsample & 0x0000ff00) << 8 | (lsample & 0x000000ff) << 24;
229 *(optr++) =
230 (rsample & 0xff000000) >> 24 | (rsample & 0x00ff0000) >> 8 |
231 (rsample & 0x0000ff00) << 8 | (rsample & 0x000000ff) << 24;
232 }
233 }
234 #endif
235 }
236 break;
237 default:
238 break;
239 }
240 }
241
242 #if !WIN
243 inline
244 #endif
245 void _apply_cross(struct buffer *outputbuf, frames_t out_frames, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) {
246 s32_t *ptr = (s32_t *)(void *)outputbuf->readp;
247 frames_t count = out_frames * 2;
248 while (count--) {
249 if (*cross_ptr > (s32_t *)outputbuf->wrap) {
250 *cross_ptr -= outputbuf->size / BYTES_PER_FRAME * 2;
251 }
252 *ptr = gain(cross_gain_out, *ptr) + gain(cross_gain_in, **cross_ptr);
253 ptr++; (*cross_ptr)++;
254 }
255 }
256
257 #if !WIN
258 inline
259 #endif
260 void _apply_gain(struct buffer *outputbuf, frames_t count, s32_t gainL, s32_t gainR) {
261 s32_t *ptrL = (s32_t *)(void *)outputbuf->readp;
262 s32_t *ptrR = (s32_t *)(void *)outputbuf->readp + 1;
263 while (count--) {
264 *ptrL = gain(gainL, *ptrL);
265 *ptrR = gain(gainR, *ptrR);
266 ptrL += 2;
267 ptrR += 2;
268 }
269 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // Stdout output
21
22 #include "squeezelite.h"
23
24 #define FRAME_BLOCK MAX_SILENCE_FRAMES
25
26 static log_level loglevel;
27
28 static bool running = true;
29
30 extern struct outputstate output;
31 extern struct buffer *outputbuf;
32
33 #define LOCK mutex_lock(outputbuf->mutex)
34 #define UNLOCK mutex_unlock(outputbuf->mutex)
35
36 extern u8_t *silencebuf;
37 #if DSD
38 extern u8_t *silencebuf_dop;
39 #endif
40
41 // buffer to hold output data so we can block on writing outside of output lock, allocated on init
42 static u8_t *buf;
43 static unsigned buffill;
44 static int bytes_per_frame;
45
46 static int _stdout_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
47 s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) {
48
49 u8_t *obuf;
50
51 if (!silence) {
52
53 if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
54 _apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
55 }
56
57 obuf = outputbuf->readp;
58
59 } else {
60
61 obuf = silencebuf;
62 }
63
64 IF_DSD(
65 if (output.dop) {
66 if (silence) {
67 obuf = silencebuf_dop;
68 }
69 update_dop((u32_t *)obuf, out_frames, output.invert && !silence);
70 }
71 )
72
73 _scale_and_pack_frames(buf + buffill * bytes_per_frame, (s32_t *)(void *)obuf, out_frames, gainL, gainR, output.format);
74
75 buffill += out_frames;
76
77 return (int)out_frames;
78 }
79
80 static void *output_thread() {
81
82 LOCK;
83
84 switch (output.format) {
85 case S32_LE:
86 bytes_per_frame = 4 * 2; break;
87 case S24_3LE:
88 bytes_per_frame = 3 * 2; break;
89 case S16_LE:
90 bytes_per_frame = 2 * 2; break;
91 default:
92 bytes_per_frame = 4 * 2; break;
93 break;
94 }
95
96 UNLOCK;
97
98 while (running) {
99
100 LOCK;
101
102 output.device_frames = 0;
103 output.updated = gettime_ms();
104 output.frames_played_dmp = output.frames_played;
105
106 _output_frames(FRAME_BLOCK);
107
108 UNLOCK;
109
110 if (buffill) {
111 fwrite(buf, bytes_per_frame, buffill, stdout);
112 buffill = 0;
113 }
114
115 }
116
117 return 0;
118 }
119
120 static thread_type thread;
121
122 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay) {
123 loglevel = level;
124
125 LOG_INFO("init output stdout");
126
127 buf = malloc(FRAME_BLOCK * BYTES_PER_FRAME);
128 if (!buf) {
129 LOG_ERROR("unable to malloc buf");
130 return;
131 }
132 buffill = 0;
133
134 memset(&output, 0, sizeof(output));
135
136 output.format = S32_LE;
137 output.start_frames = FRAME_BLOCK * 2;
138 output.write_cb = &_stdout_write_frames;
139 output.rate_delay = rate_delay;
140
141 if (params) {
142 if (!strcmp(params, "32")) output.format = S32_LE;
143 if (!strcmp(params, "24")) output.format = S24_3LE;
144 if (!strcmp(params, "16")) output.format = S16_LE;
145 }
146
147 // ensure output rate is specified to avoid test open
148 if (!rates[0]) {
149 rates[0] = 44100;
150 }
151
152 output_init_common(level, "-", output_buf_size, rates, 0);
153
154 #if LINUX || OSX || FREEBSD
155 pthread_attr_t attr;
156 pthread_attr_init(&attr);
157 pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + OUTPUT_THREAD_STACK_SIZE);
158 pthread_create(&thread, &attr, output_thread, NULL);
159 pthread_attr_destroy(&attr);
160 #endif
161 #if WIN
162 thread = CreateThread(NULL, OUTPUT_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&output_thread, NULL, 0, NULL);
163 #endif
164 }
165
166 void output_close_stdout(void) {
167 LOG_INFO("close output");
168
169 LOCK;
170 running = false;
171 UNLOCK;
172
173 free(buf);
174
175 output_close_common();
176 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // Export audio samples for visualiser process (16 bit only best endevours)
21
22 #include "squeezelite.h"
23
24 #if VISEXPORT
25
26 #include <sys/stat.h>
27 #include <sys/mman.h>
28 #include <fcntl.h>
29
30 #define VIS_BUF_SIZE 16384
31 #define VIS_LOCK_NS 1000000 // ns to wait for vis wrlock
32
33 static struct vis_t {
34 pthread_rwlock_t rwlock;
35 u32_t buf_size;
36 u32_t buf_index;
37 bool running;
38 u32_t rate;
39 time_t updated;
40 s16_t buffer[VIS_BUF_SIZE];
41 } *vis_mmap = NULL;
42
43 static char vis_shm_path[40];
44 static int vis_fd = -1;
45
46 static log_level loglevel;
47
48 // attempt to write audio to vis_mmap but do not wait more than VIS_LOCK_NS to get wrlock
49 // this can result in missing audio export to the mmap region, but this is preferable dropping audio
50 void _vis_export(struct buffer *outputbuf, struct outputstate *output, frames_t out_frames, bool silence) {
51 if (vis_mmap) {
52 int err;
53
54 err = pthread_rwlock_trywrlock(&vis_mmap->rwlock);
55 if (err) {
56 struct timespec ts;
57 clock_gettime(CLOCK_REALTIME, &ts);
58 ts.tv_nsec += VIS_LOCK_NS;
59 if (ts.tv_nsec > 1000000000) {
60 ts.tv_sec += 1;
61 ts.tv_nsec -= 1000000000;
62 }
63 err = pthread_rwlock_timedwrlock(&vis_mmap->rwlock, &ts);
64 }
65
66 if (err) {
67 LOG_DEBUG("failed to get wrlock - skipping visulizer export");
68
69 } else {
70
71 if (silence) {
72 vis_mmap->running = false;
73 } else {
74 frames_t vis_cnt = out_frames;
75 s32_t *ptr = (s32_t *) outputbuf->readp;
76 unsigned i = vis_mmap->buf_index;
77
78 if (!output->current_replay_gain) {
79 while (vis_cnt--) {
80 vis_mmap->buffer[i++] = *(ptr++) >> 16;
81 vis_mmap->buffer[i++] = *(ptr++) >> 16;
82 if (i == VIS_BUF_SIZE) i = 0;
83 }
84 } else {
85 while (vis_cnt--) {
86 vis_mmap->buffer[i++] = gain(*(ptr++), output->current_replay_gain) >> 16;
87 vis_mmap->buffer[i++] = gain(*(ptr++), output->current_replay_gain) >> 16;
88 if (i == VIS_BUF_SIZE) i = 0;
89 }
90 }
91
92 vis_mmap->updated = time(NULL);
93 vis_mmap->running = true;
94 vis_mmap->buf_index = i;
95 vis_mmap->rate = output->current_sample_rate;
96 }
97
98 pthread_rwlock_unlock(&vis_mmap->rwlock);
99 }
100 }
101 }
102
103 void vis_stop(void) {
104 if (vis_mmap) {
105 pthread_rwlock_wrlock(&vis_mmap->rwlock);
106 vis_mmap->running = false;
107 pthread_rwlock_unlock(&vis_mmap->rwlock);
108 }
109 }
110
111 void output_vis_init(log_level level, u8_t *mac) {
112 loglevel = level;
113
114 sprintf(vis_shm_path, "/squeezelite-%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
115
116 mode_t old_mask = umask(000); // allow any user to read our shm when created
117
118 vis_fd = shm_open(vis_shm_path, O_CREAT | O_RDWR, 0666);
119 if (vis_fd != -1) {
120 if (ftruncate(vis_fd, sizeof(struct vis_t)) == 0) {
121 vis_mmap = (struct vis_t *)mmap(NULL, sizeof(struct vis_t), PROT_READ | PROT_WRITE, MAP_SHARED, vis_fd, 0);
122 }
123 }
124
125 if (vis_mmap > 0) {
126 pthread_rwlockattr_t attr;
127 pthread_rwlockattr_init(&attr);
128 pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
129 pthread_rwlock_init(&vis_mmap->rwlock, &attr);
130 vis_mmap->buf_size = VIS_BUF_SIZE;
131 vis_mmap->running = false;
132 vis_mmap->rate = 44100;
133 pthread_rwlockattr_destroy(&attr);
134 LOG_INFO("opened visulizer shared memory as %s", vis_shm_path);
135 } else {
136 LOG_WARN("unable to open visualizer shared memory");
137 vis_mmap = NULL;
138 }
139
140 umask(old_mask);
141 }
142
143 #endif // VISEXPORT
+386
-0
pcm.c less more
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 extern log_level loglevel;
23
24 extern struct buffer *streambuf;
25 extern struct buffer *outputbuf;
26 extern struct streamstate stream;
27 extern struct outputstate output;
28 extern struct decodestate decode;
29 extern struct processstate process;
30
31 #define LOCK_S mutex_lock(streambuf->mutex)
32 #define UNLOCK_S mutex_unlock(streambuf->mutex)
33 #define LOCK_O mutex_lock(outputbuf->mutex)
34 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
35 #if PROCESS
36 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
37 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
38 #define LOCK_O_not_direct if (!decode.direct) mutex_lock(outputbuf->mutex)
39 #define UNLOCK_O_not_direct if (!decode.direct) mutex_unlock(outputbuf->mutex)
40 #define IF_DIRECT(x) if (decode.direct) { x }
41 #define IF_PROCESS(x) if (!decode.direct) { x }
42 #else
43 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
44 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
45 #define LOCK_O_not_direct
46 #define UNLOCK_O_not_direct
47 #define IF_DIRECT(x) { x }
48 #define IF_PROCESS(x)
49 #endif
50
51 #define MAX_DECODE_FRAMES 4096
52
53 static u32_t sample_rates[] = {
54 11025, 22050, 32000, 44100, 48000, 8000, 12000, 16000, 24000, 96000, 88200, 176400, 192000, 352800, 384000
55 };
56
57 static u32_t sample_rate;
58 static u32_t sample_size;
59 static u32_t channels;
60 static bool bigendian;
61 static bool limit;
62 static u32_t audio_left;
63 static u32_t bytes_per_frame;
64
65 typedef enum { UNKNOWN = 0, WAVE, AIFF } header_format;
66
67 static void _check_header(void) {
68 u8_t *ptr = streambuf->readp;
69 unsigned bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
70 header_format format = UNKNOWN;
71
72 // simple parsing of wav and aiff headers and get to samples
73
74 if (bytes > 12) {
75 if (!memcmp(ptr, "RIFF", 4) && !memcmp(ptr+8, "WAVE", 4)) {
76 LOG_INFO("WAVE");
77 format = WAVE;
78 } else if (!memcmp(ptr, "FORM", 4) && (!memcmp(ptr+8, "AIFF", 4) || !memcmp(ptr+8, "AIFC", 4))) {
79 LOG_INFO("AIFF");
80 format = AIFF;
81 }
82 }
83
84 if (format != UNKNOWN) {
85 ptr += 12;
86 bytes -= 12;
87
88 while (bytes >= 8) {
89 char id[5];
90 unsigned len;
91 memcpy(id, ptr, 4);
92 id[4] = '\0';
93
94 if (format == WAVE) {
95 len = *(ptr+4) | *(ptr+5) << 8 | *(ptr+6) << 16| *(ptr+7) << 24;
96 } else {
97 len = *(ptr+4) << 24 | *(ptr+5) << 16 | *(ptr+6) << 8 | *(ptr+7);
98 }
99
100 LOG_INFO("header: %s len: %d", id, len);
101
102 if (format == WAVE && !memcmp(ptr, "data", 4)) {
103 ptr += 8;
104 _buf_inc_readp(streambuf, ptr - streambuf->readp);
105 audio_left = len;
106 LOG_INFO("audio size: %u", audio_left);
107 limit = true;
108 return;
109 }
110
111 if (format == AIFF && !memcmp(ptr, "SSND", 4) && bytes >= 16) {
112 unsigned offset = *(ptr+8) << 24 | *(ptr+9) << 16 | *(ptr+10) << 8 | *(ptr+11);
113 // following 4 bytes is blocksize - ignored
114 ptr += 8 + 8;
115 _buf_inc_readp(streambuf, ptr + offset - streambuf->readp);
116 audio_left = len - 8 - offset;
117 LOG_INFO("audio size: %u", audio_left);
118 limit = true;
119 return;
120 }
121
122 if (format == WAVE && !memcmp(ptr, "fmt ", 4) && bytes >= 24) {
123 // override the server parsed values with our own
124 channels = *(ptr+10) | *(ptr+11) << 8;
125 sample_rate = *(ptr+12) | *(ptr+13) << 8 | *(ptr+14) << 16 | *(ptr+15) << 24;
126 sample_size = (*(ptr+22) | *(ptr+23) << 8) / 8;
127 bigendian = 0;
128 LOG_INFO("pcm size: %u rate: %u chan: %u bigendian: %u", sample_size, sample_rate, channels, bigendian);
129 }
130
131 if (format == AIFF && !memcmp(ptr, "COMM", 4) && bytes >= 26) {
132 int exponent;
133 // override the server parsed values with our own
134 channels = *(ptr+8) << 8 | *(ptr+9);
135 sample_size = (*(ptr+14) << 8 | *(ptr+15)) / 8;
136 bigendian = 1;
137 // sample rate is encoded as IEEE 80 bit extended format
138 // make some assumptions to simplify processing - only use first 32 bits of mantissa
139 exponent = ((*(ptr+16) & 0x7f) << 8 | *(ptr+17)) - 16383 - 31;
140 sample_rate = *(ptr+18) << 24 | *(ptr+19) << 16 | *(ptr+20) << 8 | *(ptr+21);
141 while (exponent < 0) { sample_rate >>= 1; ++exponent; }
142 while (exponent > 0) { sample_rate <<= 1; --exponent; }
143 LOG_INFO("pcm size: %u rate: %u chan: %u bigendian: %u", sample_size, sample_rate, channels, bigendian);
144 }
145
146 if (bytes >= len + 8) {
147 ptr += len + 8;
148 bytes -= (len + 8);
149 } else {
150 LOG_WARN("run out of data");
151 return;
152 }
153 }
154
155 } else {
156 LOG_WARN("unknown format - can't parse header");
157 }
158 }
159
160 static decode_state pcm_decode(void) {
161 unsigned bytes, in, out;
162 frames_t frames, count;
163 u32_t *optr;
164 u8_t *iptr;
165 u8_t tmp[16];
166
167 LOCK_S;
168
169 if (decode.new_stream && stream.state == STREAMING_FILE) {
170 _check_header();
171 }
172
173 LOCK_O_direct;
174
175 bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
176
177 IF_DIRECT(
178 out = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
179 );
180 IF_PROCESS(
181 out = process.max_in_frames;
182 );
183
184 if ((stream.state <= DISCONNECT && bytes == 0) || (limit && audio_left == 0)) {
185 UNLOCK_O_direct;
186 UNLOCK_S;
187 return DECODE_COMPLETE;
188 }
189
190 if (decode.new_stream) {
191 LOG_INFO("setting track_start");
192 LOCK_O_not_direct;
193 output.next_sample_rate = decode_newstream(sample_rate, output.supported_rates);
194 output.track_start = outputbuf->writep;
195 IF_DSD( output.next_dop = false; )
196 if (output.fade_mode) _checkfade(true);
197 decode.new_stream = false;
198 UNLOCK_O_not_direct;
199 IF_PROCESS(
200 out = process.max_in_frames;
201 );
202 bytes_per_frame = channels * sample_size;
203 }
204
205 IF_DIRECT(
206 optr = (u32_t *)outputbuf->writep;
207 );
208 IF_PROCESS(
209 optr = (u32_t *)process.inbuf;
210 );
211 iptr = (u8_t *)streambuf->readp;
212
213 in = bytes / bytes_per_frame;
214
215 // handle frame wrapping round end of streambuf
216 // - only need if resizing of streambuf does not avoid this, could occur in localfile case
217 if (in == 0 && bytes > 0 && _buf_used(streambuf) >= bytes_per_frame) {
218 memcpy(tmp, iptr, bytes);
219 memcpy(tmp + bytes, streambuf->buf, bytes_per_frame - bytes);
220 iptr = tmp;
221 in = 1;
222 }
223
224 frames = min(in, out);
225 frames = min(frames, MAX_DECODE_FRAMES);
226
227 if (limit && frames * bytes_per_frame > audio_left) {
228 LOG_INFO("reached end of audio");
229 frames = audio_left / bytes_per_frame;
230 }
231
232 count = frames * channels;
233
234 if (channels == 2) {
235 if (sample_size == 1) {
236 while (count--) {
237 *optr++ = *iptr++ << 24;
238 }
239 } else if (sample_size == 2) {
240 if (bigendian) {
241 while (count--) {
242 *optr++ = *(iptr) << 24 | *(iptr+1) << 16;
243 iptr += 2;
244 }
245 } else {
246 while (count--) {
247 *optr++ = *(iptr) << 16 | *(iptr+1) << 24;
248 iptr += 2;
249 }
250 }
251 } else if (sample_size == 3) {
252 if (bigendian) {
253 while (count--) {
254 *optr++ = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8;
255 iptr += 3;
256 }
257 } else {
258 while (count--) {
259 *optr++ = *(iptr) << 8 | *(iptr+1) << 16 | *(iptr+2) << 24;
260 iptr += 3;
261 }
262 }
263 } else if (sample_size == 4) {
264 if (bigendian) {
265 while (count--) {
266 *optr++ = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8 | *(iptr+3);
267 iptr += 4;
268 }
269 } else {
270 while (count--) {
271 *optr++ = *(iptr) | *(iptr+1) << 8 | *(iptr+2) << 16 | *(iptr+3) << 24;
272 iptr += 4;
273 }
274 }
275 }
276 } else if (channels == 1) {
277 if (sample_size == 1) {
278 while (count--) {
279 *optr = *iptr++ << 24;
280 *(optr+1) = *optr;
281 optr += 2;
282 }
283 } else if (sample_size == 2) {
284 if (bigendian) {
285 while (count--) {
286 *optr = *(iptr) << 24 | *(iptr+1) << 16;
287 *(optr+1) = *optr;
288 iptr += 2;
289 optr += 2;
290 }
291 } else {
292 while (count--) {
293 *optr = *(iptr) << 16 | *(iptr+1) << 24;
294 *(optr+1) = *optr;
295 iptr += 2;
296 optr += 2;
297 }
298 }
299 } else if (sample_size == 3) {
300 if (bigendian) {
301 while (count--) {
302 *optr = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8;
303 *(optr+1) = *optr;
304 iptr += 3;
305 optr += 2;
306 }
307 } else {
308 while (count--) {
309 *optr = *(iptr) << 8 | *(iptr+1) << 16 | *(iptr+2) << 24;
310 *(optr+1) = *optr;
311 iptr += 3;
312 optr += 2;
313 }
314 }
315 } else if (sample_size == 4) {
316 if (bigendian) {
317 while (count--) {
318 *optr++ = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8 | *(iptr+3);
319 *(optr+1) = *optr;
320 iptr += 4;
321 optr += 2;
322 }
323 } else {
324 while (count--) {
325 *optr++ = *(iptr) | *(iptr+1) << 8 | *(iptr+2) << 16 | *(iptr+3) << 24;
326 *(optr+1) = *optr;
327 iptr += 4;
328 optr += 2;
329 }
330 }
331 }
332 } else {
333 LOG_ERROR("unsupported channels");
334 }
335
336 LOG_SDEBUG("decoded %u frames", frames);
337
338 _buf_inc_readp(streambuf, frames * bytes_per_frame);
339
340 if (limit) {
341 audio_left -= frames * bytes_per_frame;
342 }
343
344 IF_DIRECT(
345 _buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
346 );
347 IF_PROCESS(
348 process.in_frames = frames;
349 );
350
351 UNLOCK_O_direct;
352 UNLOCK_S;
353
354 return DECODE_RUNNING;
355 }
356
357 static void pcm_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
358 sample_size = size - '0' + 1;
359 sample_rate = sample_rates[rate - '0'];
360 channels = chan - '0';
361 bigendian = (endianness == '0');
362 limit = false;
363
364 LOG_INFO("pcm size: %u rate: %u chan: %u bigendian: %u", sample_size, sample_rate, channels, bigendian);
365 buf_adjust(streambuf, sample_size * channels);
366 }
367
368 static void pcm_close(void) {
369 buf_adjust(streambuf, 1);
370 }
371
372 struct codec *register_pcm(void) {
373 static struct codec ret = {
374 'p', // id
375 "aif,pcm", // types
376 4096, // min read
377 102400, // min space
378 pcm_open, // open
379 pcm_close, // close
380 pcm_decode, // decode
381 };
382
383 LOG_INFO("using pcm to decode aif,pcm");
384 return &ret;
385 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // sample processing - only included when building with PROCESS set
21
22 #include "squeezelite.h"
23
24 #if PROCESS
25
26 extern log_level loglevel;
27
28 extern struct buffer *outputbuf;
29 extern struct decodestate decode;
30 struct processstate process;
31 extern struct codec *codec;
32
33 #define LOCK_D mutex_lock(decode.mutex);
34 #define UNLOCK_D mutex_unlock(decode.mutex);
35 #define LOCK_O mutex_lock(outputbuf->mutex)
36 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
37
38 // macros to map to processing functions - currently only resample.c
39 // this can be made more generic when multiple processing mechanisms get added
40 #if RESAMPLE
41 #define SAMPLES_FUNC resample_samples
42 #define DRAIN_FUNC resample_drain
43 #define NEWSTREAM_FUNC resample_newstream
44 #define FLUSH_FUNC resample_flush
45 #define INIT_FUNC resample_init
46 #endif
47
48
49 // transfer all processed frames to the output buf
50 static void _write_samples(void) {
51 size_t frames = process.out_frames;
52 u32_t *iptr = (u32_t *)process.outbuf;
53 unsigned cnt = 10;
54
55 LOCK_O;
56
57 while (frames > 0) {
58
59 frames_t f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
60 u32_t *optr = (u32_t *)outputbuf->writep;
61
62 if (f > 0) {
63
64 f = min(f, frames);
65
66 memcpy(optr, iptr, f * BYTES_PER_FRAME);
67
68 frames -= f;
69
70 _buf_inc_writep(outputbuf, f * BYTES_PER_FRAME);
71 iptr += f * BYTES_PER_FRAME / sizeof(*iptr);
72
73 } else if (cnt--) {
74
75 // there should normally be space in the output buffer, but may need to wait during drain phase
76 UNLOCK_O;
77 usleep(10000);
78 LOCK_O;
79
80 } else {
81
82 // bail out if no space found after 100ms to avoid locking
83 LOG_ERROR("unable to get space in output buffer");
84 UNLOCK_O;
85 return;
86 }
87 }
88
89 UNLOCK_O;
90 }
91
92 // process samples - called with decode mutex set
93 void process_samples(void) {
94
95 SAMPLES_FUNC(&process);
96
97 _write_samples();
98
99 process.in_frames = 0;
100 }
101
102 // drain at end of track - called with decode mutex set
103 void process_drain(void) {
104 bool done;
105
106 do {
107
108 done = DRAIN_FUNC(&process);
109
110 _write_samples();
111
112 } while (!done);
113
114 LOG_DEBUG("processing track complete - frames in: %lu out: %lu", process.total_in, process.total_out);
115 }
116
117 // new stream - called with decode mutex set
118 unsigned process_newstream(bool *direct, unsigned raw_sample_rate, unsigned supported_rates[]) {
119
120 bool active = NEWSTREAM_FUNC(&process, raw_sample_rate, supported_rates);
121
122 LOG_INFO("processing: %s", active ? "active" : "inactive");
123
124 *direct = !active;
125
126 if (active) {
127
128 unsigned max_in_frames, max_out_frames;
129
130 process.in_frames = process.out_frames = 0;
131 process.total_in = process.total_out = 0;
132
133 max_in_frames = codec->min_space / BYTES_PER_FRAME ;
134
135 // increase size of output buffer by 10% as output rate is not an exact multiple of input rate
136 if (process.out_sample_rate % process.in_sample_rate == 0) {
137 max_out_frames = max_in_frames * (process.out_sample_rate / process.in_sample_rate);
138 } else {
139 max_out_frames = (int)(1.1 * (float)max_in_frames * (float)process.out_sample_rate / (float)process.in_sample_rate);
140 }
141
142 if (process.max_in_frames != max_in_frames) {
143 LOG_DEBUG("creating process buf in frames: %u", max_in_frames);
144 if (process.inbuf) free(process.inbuf);
145 process.inbuf = malloc(max_in_frames * BYTES_PER_FRAME);
146 process.max_in_frames = max_in_frames;
147 }
148
149 if (process.max_out_frames != max_out_frames) {
150 LOG_DEBUG("creating process buf out frames: %u", max_out_frames);
151 if (process.outbuf) free(process.outbuf);
152 process.outbuf = malloc(max_out_frames * BYTES_PER_FRAME);
153 process.max_out_frames = max_out_frames;
154 }
155
156 if (!process.inbuf || !process.outbuf) {
157 LOG_ERROR("malloc fail creating process buffers");
158 *direct = true;
159 return raw_sample_rate;
160 }
161
162 return process.out_sample_rate;
163 }
164
165 return raw_sample_rate;
166 }
167
168 // process flush - called with decode mutex set
169 void process_flush(void) {
170
171 LOG_INFO("process flush");
172
173 FLUSH_FUNC();
174
175 process.in_frames = 0;
176 }
177
178 // init - called with no mutex
179 void process_init(char *opt) {
180
181 bool enabled = INIT_FUNC(opt);
182
183 memset(&process, 0, sizeof(process));
184
185 if (enabled) {
186 LOCK_D;
187 decode.process = true;
188 UNLOCK_D;
189 }
190 }
191
192 #endif // #if PROCESS
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // upsampling using libsoxr - only included if RESAMPLE set
21
22 #include "squeezelite.h"
23
24 #if RESAMPLE
25
26 #include <math.h>
27 #include <soxr.h>
28
29 extern log_level loglevel;
30
31 struct soxr {
32 soxr_t resampler;
33 size_t old_clips;
34 unsigned long q_recipe;
35 unsigned long q_flags;
36 double q_precision; /* Conversion precision (in bits). 20 */
37 double q_phase_response; /* 0=minimum, ... 50=linear, ... 100=maximum 50 */
38 double q_passband_end; /* 0dB pt. bandwidth to preserve; nyquist=1 0.913 */
39 double q_stopband_begin; /* Aliasing/imaging control; > passband_end 1 */
40 double scale;
41 bool max_rate;
42 bool exception;
43 #if !LINKALL
44 // soxr symbols to be dynamically loaded
45 soxr_io_spec_t (* soxr_io_spec)(soxr_datatype_t itype, soxr_datatype_t otype);
46 soxr_quality_spec_t (* soxr_quality_spec)(unsigned long recipe, unsigned long flags);
47 soxr_t (* soxr_create)(double, double, unsigned, soxr_error_t *,
48 soxr_io_spec_t const *, soxr_quality_spec_t const *, soxr_runtime_spec_t const *);
49 void (* soxr_delete)(soxr_t);
50 soxr_error_t (* soxr_process)(soxr_t, soxr_in_t, size_t, size_t *, soxr_out_t, size_t olen, size_t *);
51 size_t *(* soxr_num_clips)(soxr_t);
52 #if RESAMPLE_MP
53 soxr_runtime_spec_t (* soxr_runtime_spec)(unsigned num_threads);
54 #endif
55 // soxr_strerror is a macro so not included here
56 #endif
57 };
58
59 static struct soxr *r;
60
61 #if LINKALL
62 #define SOXR(h, fn, ...) (soxr_ ## fn)(__VA_ARGS__)
63 #else
64 #define SOXR(h, fn, ...) (h)->soxr_##fn(__VA_ARGS__)
65 #endif
66
67
68 void resample_samples(struct processstate *process) {
69 size_t idone, odone;
70 size_t clip_cnt;
71
72 soxr_error_t error =
73 SOXR(r, process, r->resampler, process->inbuf, process->in_frames, &idone, process->outbuf, process->max_out_frames, &odone);
74 if (error) {
75 LOG_INFO("soxr_process error: %s", soxr_strerror(error));
76 return;
77 }
78
79 if (idone != process->in_frames) {
80 // should not get here if buffers are big enough...
81 LOG_ERROR("should not get here - partial sox process: %u of %u processed %u of %u out",
82 (unsigned)idone, process->in_frames, (unsigned)odone, process->max_out_frames);
83 }
84
85 process->out_frames = odone;
86 process->total_in += idone;
87 process->total_out += odone;
88
89 clip_cnt = *(SOXR(r, num_clips, r->resampler));
90 if (clip_cnt - r->old_clips) {
91 LOG_SDEBUG("resampling clips: %u", (unsigned)(clip_cnt - r->old_clips));
92 r->old_clips = clip_cnt;
93 }
94 }
95
96 bool resample_drain(struct processstate *process) {
97 size_t odone;
98 size_t clip_cnt;
99
100 soxr_error_t error = SOXR(r, process, r->resampler, NULL, 0, NULL, process->outbuf, process->max_out_frames, &odone);
101 if (error) {
102 LOG_INFO("soxr_process error: %s", soxr_strerror(error));
103 return true;
104 }
105
106 process->out_frames = odone;
107 process->total_out += odone;
108
109 clip_cnt = *(SOXR(r, num_clips, r->resampler));
110 if (clip_cnt - r->old_clips) {
111 LOG_DEBUG("resampling clips: %u", (unsigned)(clip_cnt - r->old_clips));
112 r->old_clips = clip_cnt;
113 }
114
115 if (odone == 0) {
116
117 LOG_INFO("resample track complete - total track clips: %u", r->old_clips);
118
119 SOXR(r, delete, r->resampler);
120 r->resampler = NULL;
121
122 return true;
123
124 } else {
125
126 return false;
127 }
128 }
129
130 bool resample_newstream(struct processstate *process, unsigned raw_sample_rate, unsigned supported_rates[]) {
131 unsigned outrate = 0;
132 int i;
133
134 if (r->exception) {
135 // find direct match - avoid resampling
136 for (i = 0; supported_rates[i]; i++) {
137 if (raw_sample_rate == supported_rates[i]) {
138 outrate = raw_sample_rate;
139 break;
140 }
141 }
142 // else find next highest sync sample rate
143 while (!outrate && i >= 0) {
144 if (supported_rates[i] > raw_sample_rate && supported_rates[i] % raw_sample_rate == 0) {
145 outrate = supported_rates[i];
146 break;
147 }
148 i--;
149 }
150 }
151
152 if (!outrate) {
153 if (r->max_rate) {
154 // resample to max rate for device
155 outrate = supported_rates[0];
156 } else {
157 // resample to max sync sample rate
158 for (i = 0; supported_rates[i]; i++) {
159 if (supported_rates[i] % raw_sample_rate == 0 || raw_sample_rate % supported_rates[i] == 0) {
160 outrate = supported_rates[i];
161 break;
162 }
163 }
164 }
165 if (!outrate) {
166 outrate = supported_rates[0];
167 }
168 }
169
170 process->in_sample_rate = raw_sample_rate;
171 process->out_sample_rate = outrate;
172
173 if (r->resampler) {
174 SOXR(r, delete, r->resampler);
175 r->resampler = NULL;
176 }
177
178 if (raw_sample_rate != outrate) {
179
180 soxr_io_spec_t io_spec;
181 soxr_quality_spec_t q_spec;
182 soxr_error_t error;
183 #if RESAMPLE_MP
184 soxr_runtime_spec_t r_spec;
185 #endif
186
187 LOG_INFO("resampling from %u -> %u", raw_sample_rate, outrate);
188
189 io_spec = SOXR(r, io_spec, SOXR_INT32_I, SOXR_INT32_I);
190 io_spec.scale = r->scale;
191
192 q_spec = SOXR(r, quality_spec, r->q_recipe, r->q_flags);
193 if (r->q_precision > 0) {
194 q_spec.precision = r->q_precision;
195 }
196 if (r->q_passband_end > 0) {
197 q_spec.passband_end = r->q_passband_end;
198 }
199 if (r->q_stopband_begin > 0) {
200 q_spec.stopband_begin = r->q_stopband_begin;
201 }
202 if (r->q_phase_response > -1) {
203 q_spec.phase_response = r->q_phase_response;
204 }
205
206 #if RESAMPLE_MP
207 r_spec = SOXR(r, runtime_spec, 0); // make use of libsoxr OpenMP support allowing parallel execution if multiple cores
208 #endif
209
210 LOG_DEBUG("resampling with soxr_quality_spec_t[precision: %03.1f, passband_end: %03.6f, stopband_begin: %03.6f, "
211 "phase_response: %03.1f, flags: 0x%02x], soxr_io_spec_t[scale: %03.2f]", q_spec.precision,
212 q_spec.passband_end, q_spec.stopband_begin, q_spec.phase_response, q_spec.flags, io_spec.scale);
213
214 #if RESAMPLE_MP
215 r->resampler = SOXR(r, create, raw_sample_rate, outrate, 2, &error, &io_spec, &q_spec, &r_spec);
216 #else
217 r->resampler = SOXR(r, create, raw_sample_rate, outrate, 2, &error, &io_spec, &q_spec, NULL);
218 #endif
219
220 if (error) {
221 LOG_INFO("soxr_create error: %s", soxr_strerror(error));
222 return false;
223 }
224
225 r->old_clips = 0;
226 return true;
227
228 } else {
229
230 LOG_INFO("disable resampling - rates match");
231 return false;
232 }
233 }
234
235 void resample_flush(void) {
236 if (r->resampler) {
237 SOXR(r, delete, r->resampler);
238 r->resampler = NULL;
239 }
240 }
241
242 static bool load_soxr(void) {
243 #if !LINKALL
244 void *handle = dlopen(LIBSOXR, RTLD_NOW);
245 char *err;
246
247 if (!handle) {
248 LOG_INFO("dlerror: %s", dlerror());
249 return false;
250 }
251
252 r->soxr_io_spec = dlsym(handle, "soxr_io_spec");
253 r->soxr_quality_spec = dlsym(handle, "soxr_quality_spec");
254 r->soxr_create = dlsym(handle, "soxr_create");
255 r->soxr_delete = dlsym(handle, "soxr_delete");
256 r->soxr_process = dlsym(handle, "soxr_process");
257 r->soxr_num_clips = dlsym(handle, "soxr_num_clips");
258 #if RESAMPLE_MP
259 r->soxr_runtime_spec = dlsym(handle, "soxr_runtime_spec");
260 #endif
261
262 if ((err = dlerror()) != NULL) {
263 LOG_INFO("dlerror: %s", err);
264 return false;
265 }
266
267 LOG_INFO("loaded "LIBSOXR);
268 #endif
269
270 return true;
271 }
272
273 bool resample_init(char *opt) {
274 char *recipe = NULL, *flags = NULL;
275 char *atten = NULL;
276 char *precision = NULL, *passband_end = NULL, *stopband_begin = NULL, *phase_response = NULL;
277
278 r = malloc(sizeof(struct soxr));
279 if (!r) {
280 LOG_WARN("resampling disabled");
281 return false;
282 }
283
284 r->resampler = NULL;
285 r->old_clips = 0;
286 r->max_rate = false;
287 r->exception = false;
288
289 if (!load_soxr()) {
290 LOG_WARN("resampling disabled");
291 return false;
292 }
293
294 if (opt) {
295 recipe = next_param(opt, ':');
296 flags = next_param(NULL, ':');
297 atten = next_param(NULL, ':');
298 precision = next_param(NULL, ':');
299 passband_end = next_param(NULL, ':');
300 stopband_begin = next_param(NULL, ':');
301 phase_response = next_param(NULL, ':');
302 }
303
304 // default to HQ (20 bit) if not user specified
305 r->q_recipe = SOXR_HQ;
306 r->q_flags = 0;
307 // default to 1db of attenuation if not user specified
308 r->scale = pow(10, -1.0 / 20);
309 // override recipe derived values with user specified values
310 r->q_precision = 0;
311 r->q_passband_end = 0;
312 r->q_stopband_begin = 0;
313 r->q_phase_response = -1;
314
315 if (recipe && recipe[0] != '\0') {
316 if (strchr(recipe, 'v')) r->q_recipe = SOXR_VHQ;
317 if (strchr(recipe, 'h')) r->q_recipe = SOXR_HQ;
318 if (strchr(recipe, 'm')) r->q_recipe = SOXR_MQ;
319 if (strchr(recipe, 'l')) r->q_recipe = SOXR_LQ;
320 if (strchr(recipe, 'q')) r->q_recipe = SOXR_QQ;
321 if (strchr(recipe, 'L')) r->q_recipe |= SOXR_LINEAR_PHASE;
322 if (strchr(recipe, 'I')) r->q_recipe |= SOXR_INTERMEDIATE_PHASE;
323 if (strchr(recipe, 'M')) r->q_recipe |= SOXR_MINIMUM_PHASE;
324 if (strchr(recipe, 's')) r->q_recipe |= SOXR_STEEP_FILTER;
325 // X = async resampling to max_rate
326 if (strchr(recipe, 'X')) r->max_rate = true;
327 // E = exception, only resample if native rate is not supported
328 if (strchr(recipe, 'E')) r->exception = true;
329 }
330
331 if (flags) {
332 r->q_flags = strtoul(flags, 0, 16);
333 }
334
335 if (atten) {
336 double scale = pow(10, -atof(atten) / 20);
337 if (scale > 0 && scale <= 1.0) {
338 r->scale = scale;
339 }
340 }
341
342 if (precision) {
343 r->q_precision = atof(precision);
344 }
345
346 if (passband_end) {
347 r->q_passband_end = atof(passband_end) / 100;
348 }
349
350 if (stopband_begin) {
351 r->q_stopband_begin = atof(stopband_begin) / 100;
352 }
353
354 if (phase_response) {
355 r->q_phase_response = atof(phase_response);
356 }
357
358 LOG_INFO("resampling %s recipe: 0x%02x, flags: 0x%02x, scale: %03.2f, precision: %03.1f, passband_end: %03.5f, stopband_begin: %03.5f, phase_response: %03.1f",
359 r->max_rate ? "async" : "sync",
360 r->q_recipe, r->q_flags, r->scale, r->q_precision, r->q_passband_end, r->q_stopband_begin, r->q_phase_response);
361
362 return true;
363 }
364
365 #endif // #if RESAMPLE
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21 #include "slimproto.h"
22
23 static log_level loglevel;
24
25 #define PORT 3483
26
27 #define MAXBUF 4096
28
29 #if SL_LITTLE_ENDIAN
30 #define LOCAL_PLAYER_IP 0x0100007f // 127.0.0.1
31 #define LOCAL_PLAYER_PORT 0x9b0d // 3483
32 #else
33 #define LOCAL_PLAYER_IP 0x7f000001 // 127.0.0.1
34 #define LOCAL_PLAYER_PORT 0x0d9b // 3483
35 #endif
36
37 static sockfd sock = -1;
38 static in_addr_t slimproto_ip = 0;
39
40 extern struct buffer *streambuf;
41 extern struct buffer *outputbuf;
42
43 extern struct streamstate stream;
44 extern struct outputstate output;
45 extern struct decodestate decode;
46
47 extern struct codec *codecs[];
48 #if IR
49 extern struct irstate ir;
50 #endif
51
52 event_event wake_e;
53
54 #define LOCK_S mutex_lock(streambuf->mutex)
55 #define UNLOCK_S mutex_unlock(streambuf->mutex)
56 #define LOCK_O mutex_lock(outputbuf->mutex)
57 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
58 #define LOCK_D mutex_lock(decode.mutex)
59 #define UNLOCK_D mutex_unlock(decode.mutex)
60 #if IR
61 #define LOCK_I mutex_lock(ir.mutex)
62 #define UNLOCK_I mutex_unlock(ir.mutex)
63 #endif
64
65 static struct {
66 u32_t updated;
67 u32_t stream_start;
68 u32_t stream_full;
69 u32_t stream_size;
70 u64_t stream_bytes;
71 u32_t output_full;
72 u32_t output_size;
73 u32_t frames_played;
74 u32_t device_frames;
75 u32_t current_sample_rate;
76 u32_t last;
77 stream_state stream_state;
78 } status;
79
80 int autostart;
81 bool sentSTMu, sentSTMo, sentSTMl;
82 u32_t new_server;
83 char *new_server_cap;
84 #define PLAYER_NAME_LEN 64
85 char player_name[PLAYER_NAME_LEN + 1] = "";
86 const char *name_file = NULL;
87
88 void send_packet(u8_t *packet, size_t len) {
89 u8_t *ptr = packet;
90 unsigned try = 0;
91 ssize_t n;
92
93 while (len) {
94 n = send(sock, ptr, len, MSG_NOSIGNAL);
95 if (n <= 0) {
96 if (n < 0 && last_error() == ERROR_WOULDBLOCK && try < 10) {
97 LOG_DEBUG("retrying (%d) writing to socket", ++try);
98 usleep(1000);
99 continue;
100 }
101 LOG_INFO("failed writing to socket: %s", strerror(last_error()));
102 return;
103 }
104 ptr += n;
105 len -= n;
106 }
107 }
108
109 static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t mac[6]) {
110 const char *base_cap = "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION;
111 struct HELO_packet pkt;
112
113 memset(&pkt, 0, sizeof(pkt));
114 memcpy(&pkt.opcode, "HELO", 4);
115 pkt.length = htonl(sizeof(struct HELO_packet) - 8 + strlen(base_cap) + strlen(fixed_cap) + strlen(var_cap));
116 pkt.deviceid = 12; // squeezeplay
117 pkt.revision = 0;
118 packn(&pkt.wlan_channellist, reconnect ? 0x4000 : 0x0000);
119 packN(&pkt.bytes_received_H, (u64_t)status.stream_bytes >> 32);
120 packN(&pkt.bytes_received_L, (u64_t)status.stream_bytes & 0xffffffff);
121 memcpy(pkt.mac, mac, 6);
122
123 LOG_INFO("mac: %02x:%02x:%02x:%02x:%02x:%02x", pkt.mac[0], pkt.mac[1], pkt.mac[2], pkt.mac[3], pkt.mac[4], pkt.mac[5]);
124
125 LOG_INFO("cap: %s%s%s", base_cap, fixed_cap, var_cap);
126
127 send_packet((u8_t *)&pkt, sizeof(pkt));
128 send_packet((u8_t *)base_cap, strlen(base_cap));
129 send_packet((u8_t *)fixed_cap, strlen(fixed_cap));
130 send_packet((u8_t *)var_cap, strlen(var_cap));
131 }
132
133 static void sendSTAT(const char *event, u32_t server_timestamp) {
134 struct STAT_packet pkt;
135 u32_t now = gettime_ms();
136 u32_t ms_played;
137
138 if (status.current_sample_rate && status.frames_played && status.frames_played > status.device_frames) {
139 ms_played = (u32_t)(((u64_t)(status.frames_played - status.device_frames) * (u64_t)1000) / (u64_t)status.current_sample_rate);
140 if (now > status.updated) ms_played += (now - status.updated);
141 LOG_SDEBUG("ms_played: %u (frames_played: %u device_frames: %u)", ms_played, status.frames_played, status.device_frames);
142 } else if (status.frames_played && now > status.stream_start) {
143 ms_played = now - status.stream_start;
144 LOG_SDEBUG("ms_played: %u using elapsed time (frames_played: %u device_frames: %u)", ms_played, status.frames_played, status.device_frames);
145 } else {
146 LOG_SDEBUG("ms_played: 0");
147 ms_played = 0;
148 }
149
150 memset(&pkt, 0, sizeof(struct STAT_packet));
151 memcpy(&pkt.opcode, "STAT", 4);
152 pkt.length = htonl(sizeof(struct STAT_packet) - 8);
153 memcpy(&pkt.event, event, 4);
154 // num_crlf
155 // mas_initialized; mas_mode;
156 packN(&pkt.stream_buffer_fullness, status.stream_full);
157 packN(&pkt.stream_buffer_size, status.stream_size);
158 packN(&pkt.bytes_received_H, (u64_t)status.stream_bytes >> 32);
159 packN(&pkt.bytes_received_L, (u64_t)status.stream_bytes & 0xffffffff);
160 pkt.signal_strength = 0xffff;
161 packN(&pkt.jiffies, now);
162 packN(&pkt.output_buffer_size, status.output_size);
163 packN(&pkt.output_buffer_fullness, status.output_full);
164 packN(&pkt.elapsed_seconds, ms_played / 1000);
165 // voltage;
166 packN(&pkt.elapsed_milliseconds, ms_played);
167 pkt.server_timestamp = server_timestamp; // keep this is server format - don't unpack/pack
168 // error_code;
169
170 LOG_DEBUG("STAT: %s", event);
171
172 if (loglevel == lSDEBUG) {
173 LOG_SDEBUG("received bytesL: %u streambuf: %u outputbuf: %u calc elapsed: %u real elapsed: %u (diff: %d) device: %u delay: %d",
174 (u32_t)status.stream_bytes, status.stream_full, status.output_full, ms_played, now - status.stream_start,
175 ms_played - now + status.stream_start, status.device_frames * 1000 / status.current_sample_rate, now - status.updated);
176 }
177
178 send_packet((u8_t *)&pkt, sizeof(pkt));
179 }
180
181 static void sendDSCO(disconnect_code disconnect) {
182 struct DSCO_packet pkt;
183
184 memset(&pkt, 0, sizeof(pkt));
185 memcpy(&pkt.opcode, "DSCO", 4);
186 pkt.length = htonl(sizeof(pkt) - 8);
187 pkt.reason = disconnect & 0xFF;
188
189 LOG_DEBUG("DSCO: %d", disconnect);
190
191 send_packet((u8_t *)&pkt, sizeof(pkt));
192 }
193
194 static void sendRESP(const char *header, size_t len) {
195 struct RESP_header pkt_header;
196
197 memset(&pkt_header, 0, sizeof(pkt_header));
198 memcpy(&pkt_header.opcode, "RESP", 4);
199 pkt_header.length = htonl(sizeof(pkt_header) + len - 8);
200
201 LOG_DEBUG("RESP");
202
203 send_packet((u8_t *)&pkt_header, sizeof(pkt_header));
204 send_packet((u8_t *)header, len);
205 }
206
207 static void sendMETA(const char *meta, size_t len) {
208 struct META_header pkt_header;
209
210 memset(&pkt_header, 0, sizeof(pkt_header));
211 memcpy(&pkt_header.opcode, "META", 4);
212 pkt_header.length = htonl(sizeof(pkt_header) + len - 8);
213
214 LOG_DEBUG("META");
215
216 send_packet((u8_t *)&pkt_header, sizeof(pkt_header));
217 send_packet((u8_t *)meta, len);
218 }
219
220 static void sendSETDName(const char *name) {
221 struct SETD_header pkt_header;
222
223 memset(&pkt_header, 0, sizeof(pkt_header));
224 memcpy(&pkt_header.opcode, "SETD", 4);
225
226 pkt_header.id = 0; // id 0 is playername S:P:Squeezebox2
227 pkt_header.length = htonl(sizeof(pkt_header) + strlen(name) + 1 - 8);
228
229 LOG_DEBUG("set playername: %s", name);
230
231 send_packet((u8_t *)&pkt_header, sizeof(pkt_header));
232 send_packet((u8_t *)name, strlen(name) + 1);
233 }
234
235 #if IR
236 void sendIR(u32_t code, u32_t ts) {
237 struct IR_packet pkt;
238
239 memset(&pkt, 0, sizeof(pkt));
240 memcpy(&pkt.opcode, "IR ", 4);
241 pkt.length = htonl(sizeof(pkt) - 8);
242
243 packN(&pkt.jiffies, ts);
244 pkt.ir_code = htonl(code);
245
246 LOG_DEBUG("IR: ir code: 0x%x ts: %u", code, ts);
247
248 send_packet((u8_t *)&pkt, sizeof(pkt));
249 }
250 #endif
251
252 static void process_strm(u8_t *pkt, int len) {
253 struct strm_packet *strm = (struct strm_packet *)pkt;
254
255 LOG_DEBUG("strm command %c", strm->command);
256
257 switch(strm->command) {
258 case 't':
259 sendSTAT("STMt", strm->replay_gain); // STMt replay_gain is no longer used to track latency, but support it
260 break;
261 case 'q':
262 decode_flush();
263 output_flush();
264 status.frames_played = 0;
265 stream_disconnect();
266 sendSTAT("STMf", 0);
267 buf_flush(streambuf);
268 break;
269 case 'f':
270 decode_flush();
271 output_flush();
272 status.frames_played = 0;
273 if (stream_disconnect()) {
274 sendSTAT("STMf", 0);
275 }
276 buf_flush(streambuf);
277 break;
278 case 'p':
279 {
280 unsigned interval = unpackN(&strm->replay_gain);
281 LOCK_O;
282 output.pause_frames = interval * status.current_sample_rate / 1000;
283 if (interval) {
284 output.state = OUTPUT_PAUSE_FRAMES;
285 } else {
286 output.state = OUTPUT_STOPPED;
287 output.stop_time = gettime_ms();
288 }
289 UNLOCK_O;
290 if (!interval) sendSTAT("STMp", 0);
291 LOG_DEBUG("pause interval: %u", interval);
292 }
293 break;
294 case 'a':
295 {
296 unsigned interval = unpackN(&strm->replay_gain);
297 LOCK_O;
298 output.skip_frames = interval * status.current_sample_rate / 1000;
299 output.state = OUTPUT_SKIP_FRAMES;
300 UNLOCK_O;
301 LOG_DEBUG("skip ahead interval: %u", interval);
302 }
303 break;
304 case 'u':
305 {
306 unsigned jiffies = unpackN(&strm->replay_gain);
307 LOCK_O;
308 output.state = jiffies ? OUTPUT_START_AT : OUTPUT_RUNNING;
309 output.start_at = jiffies;
310 UNLOCK_O;
311 LOG_DEBUG("unpause at: %u now: %u", jiffies, gettime_ms());
312 sendSTAT("STMr", 0);
313 }
314 break;
315 case 's':
316 {
317 unsigned header_len = len - sizeof(struct strm_packet);
318 char *header = (char *)(pkt + sizeof(struct strm_packet));
319 in_addr_t ip = (in_addr_t)strm->server_ip; // keep in network byte order
320 u16_t port = strm->server_port; // keep in network byte order
321 if (ip == 0) ip = slimproto_ip;
322
323 LOG_DEBUG("strm s autostart: %c transition period: %u transition type: %u codec: %c",
324 strm->autostart, strm->transition_period, strm->transition_type - '0', strm->format);
325
326 autostart = strm->autostart - '0';
327 sendSTAT("STMf", 0);
328 if (header_len > MAX_HEADER -1) {
329 LOG_WARN("header too long: %u", header_len);
330 break;
331 }
332 if (strm->format != '?') {
333 codec_open(strm->format, strm->pcm_sample_size, strm->pcm_sample_rate, strm->pcm_channels, strm->pcm_endianness);
334 } else if (autostart >= 2) {
335 // extension to slimproto to allow server to detect codec from response header and send back in codc message
336 LOG_DEBUG("streaming unknown codec");
337 } else {
338 LOG_WARN("unknown codec requires autostart >= 2");
339 break;
340 }
341 if (ip == LOCAL_PLAYER_IP && port == LOCAL_PLAYER_PORT) {
342 // extension to slimproto for LocalPlayer - header is filename not http header, don't expect cont
343 stream_file(header, header_len, strm->threshold * 1024);
344 autostart -= 2;
345 } else {
346 stream_sock(ip, port, header, header_len, strm->threshold * 1024, autostart >= 2);
347 }
348 sendSTAT("STMc", 0);
349 sentSTMu = sentSTMo = sentSTMl = false;
350 LOCK_O;
351 output.threshold = strm->output_threshold;
352 output.next_replay_gain = unpackN(&strm->replay_gain);
353 output.fade_mode = strm->transition_type - '0';
354 output.fade_secs = strm->transition_period;
355 output.invert = (strm->flags & 0x03) == 0x03;
356 LOG_DEBUG("set fade mode: %u", output.fade_mode);
357 UNLOCK_O;
358 }
359 break;
360 default:
361 LOG_WARN("unhandled strm %c", strm->command);
362 break;
363 }
364 }
365
366 static void process_cont(u8_t *pkt, int len) {
367 struct cont_packet *cont = (struct cont_packet *)pkt;
368 cont->metaint = unpackN(&cont->metaint);
369
370 LOG_DEBUG("cont metaint: %u loop: %u", cont->metaint, cont->loop);
371
372 if (autostart > 1) {
373 autostart -= 2;
374 LOCK_S;
375 if (stream.state == STREAMING_WAIT) {
376 stream.state = STREAMING_BUFFERING;
377 stream.meta_interval = stream.meta_next = cont->metaint;
378 }
379 UNLOCK_S;
380 wake_controller();
381 }
382 }
383
384 static void process_codc(u8_t *pkt, int len) {
385 struct codc_packet *codc = (struct codc_packet *)pkt;
386
387 LOG_DEBUG("codc: %c", codc->format);
388 codec_open(codc->format, codc->pcm_sample_size, codc->pcm_sample_rate, codc->pcm_channels, codc->pcm_endianness);
389 }
390
391 static void process_aude(u8_t *pkt, int len) {
392 struct aude_packet *aude = (struct aude_packet *)pkt;
393
394 LOG_DEBUG("enable spdif: %d dac: %d", aude->enable_spdif, aude->enable_dac);
395
396 LOCK_O;
397 if (!aude->enable_spdif && output.state != OUTPUT_OFF) {
398 output.state = OUTPUT_OFF;
399 }
400 if (aude->enable_spdif && output.state == OUTPUT_OFF && !output.idle_to) {
401 output.state = OUTPUT_STOPPED;
402 output.stop_time = gettime_ms();
403 }
404 UNLOCK_O;
405 }
406
407 static void process_audg(u8_t *pkt, int len) {
408 struct audg_packet *audg = (struct audg_packet *)pkt;
409 audg->gainL = unpackN(&audg->gainL);
410 audg->gainR = unpackN(&audg->gainR);
411
412 LOG_DEBUG("audg gainL: %u gainR: %u adjust: %u", audg->gainL, audg->gainR, audg->adjust);
413
414 set_volume(audg->adjust ? audg->gainL : FIXED_ONE, audg->adjust ? audg->gainR : FIXED_ONE);
415 }
416
417 static void process_setd(u8_t *pkt, int len) {
418 struct setd_packet *setd = (struct setd_packet *)pkt;
419
420 // handle player name query and change
421 if (setd->id == 0) {
422 if (len == 5) {
423 if (strlen(player_name)) {
424 sendSETDName(player_name);
425 }
426 } else if (len > 5) {
427 strncpy(player_name, setd->data, PLAYER_NAME_LEN);
428 player_name[PLAYER_NAME_LEN] = '\0';
429 LOG_INFO("set name: %s", setd->data);
430 // confirm change to server
431 sendSETDName(setd->data);
432 // write name to name_file if -N option set
433 if (name_file) {
434 FILE *fp = fopen(name_file, "w");
435 if (fp) {
436 LOG_INFO("storing name in %s", name_file);
437 fputs(player_name, fp);
438 fclose(fp);
439 } else {
440 LOG_WARN("unable to store new name in %s", name_file);
441 }
442 }
443 }
444 }
445 }
446
447 #define SYNC_CAP ",SyncgroupID="
448 #define SYNC_CAP_LEN 13
449
450 static void process_serv(u8_t *pkt, int len) {
451 struct serv_packet *serv = (struct serv_packet *)pkt;
452
453 LOG_INFO("switch server");
454
455 new_server = serv->server_ip;
456
457 if (len - sizeof(struct serv_packet) == 10) {
458 if (!new_server_cap) {
459 new_server_cap = malloc(SYNC_CAP_LEN + 10 + 1);
460 }
461 new_server_cap[0] = '\0';
462 strcat(new_server_cap, SYNC_CAP);
463 strncat(new_server_cap, (const char *)(pkt + sizeof(struct serv_packet)), 10);
464 } else {
465 if (new_server_cap) {
466 free(new_server_cap);
467 new_server_cap = NULL;
468 }
469 }
470 }
471
472 struct handler {
473 char opcode[5];
474 void (*handler)(u8_t *, int);
475 };
476
477 static struct handler handlers[] = {
478 { "strm", process_strm },
479 { "cont", process_cont },
480 { "codc", process_codc },
481 { "aude", process_aude },
482 { "audg", process_audg },
483 { "setd", process_setd },
484 { "serv", process_serv },
485 { "", NULL },
486 };
487
488 static void process(u8_t *pack, int len) {
489 struct handler *h = handlers;
490 while (h->handler && strncmp((char *)pack, h->opcode, 4)) { h++; }
491
492 if (h->handler) {
493 LOG_DEBUG("%s", h->opcode);
494 h->handler(pack, len);
495 } else {
496 pack[4] = '\0';
497 LOG_WARN("unhandled %s", (char *)pack);
498 }
499 }
500
501 static bool running;
502
503 static void slimproto_run() {
504 static u8_t buffer[MAXBUF];
505 int expect = 0;
506 int got = 0;
507 u32_t now;
508 static u32_t last = 0;
509 event_handle ehandles[2];
510 int timeouts = 0;
511
512 set_readwake_handles(ehandles, sock, wake_e);
513
514 while (running && !new_server) {
515
516 bool wake = false;
517 event_type ev;
518
519 if ((ev = wait_readwake(ehandles, 1000)) != EVENT_TIMEOUT) {
520
521 if (ev == EVENT_READ) {
522
523 if (expect > 0) {
524 int n = recv(sock, buffer + got, expect, 0);
525 if (n <= 0) {
526 if (n < 0 && last_error() == ERROR_WOULDBLOCK) {
527 continue;
528 }
529 LOG_INFO("error reading from socket: %s", n ? strerror(last_error()) : "closed");
530 return;
531 }
532 expect -= n;
533 got += n;
534 if (expect == 0) {
535 process(buffer, got);
536 got = 0;
537 }
538 } else if (expect == 0) {
539 int n = recv(sock, buffer + got, 2 - got, 0);
540 if (n <= 0) {
541 if (n < 0 && last_error() == ERROR_WOULDBLOCK) {
542 continue;
543 }
544 LOG_INFO("error reading from socket: %s", n ? strerror(last_error()) : "closed");
545 return;
546 }
547 got += n;
548 if (got == 2) {
549 expect = buffer[0] << 8 | buffer[1]; // length pack 'n'
550 got = 0;
551 if (expect > MAXBUF) {
552 LOG_ERROR("FATAL: slimproto packet too big: %d > %d", expect, MAXBUF);
553 return;
554 }
555 }
556 } else {
557 LOG_ERROR("FATAL: negative expect");
558 return;
559 }
560
561 }
562
563 if (ev == EVENT_WAKE) {
564 wake = true;
565 }
566
567 timeouts = 0;
568
569 } else if (++timeouts > 35) {
570
571 // expect message from server every 5 seconds, but 30 seconds on mysb.com so timeout after 35 seconds
572 LOG_INFO("No messages from server - connection dead");
573 return;
574 }
575
576 // update playback state when woken or every 100ms
577 now = gettime_ms();
578
579 if (wake || now - last > 100 || last > now) {
580 bool _sendSTMs = false;
581 bool _sendDSCO = false;
582 bool _sendRESP = false;
583 bool _sendMETA = false;
584 bool _sendSTMd = false;
585 bool _sendSTMt = false;
586 bool _sendSTMl = false;
587 bool _sendSTMu = false;
588 bool _sendSTMo = false;
589 bool _sendSTMn = false;
590 bool _stream_disconnect = false;
591 bool _start_output = false;
592 decode_state _decode_state;
593 disconnect_code disconnect_code;
594 static char header[MAX_HEADER];
595 size_t header_len = 0;
596 #if IR
597 bool _sendIR = false;
598 u32_t ir_code, ir_ts;
599 #endif
600 last = now;
601
602 LOCK_S;
603 status.stream_full = _buf_used(streambuf);
604 status.stream_size = streambuf->size;
605 status.stream_bytes = stream.bytes;
606 status.stream_state = stream.state;
607
608 if (stream.state == DISCONNECT) {
609 disconnect_code = stream.disconnect;
610 stream.state = STOPPED;
611 _sendDSCO = true;
612 }
613 if (!stream.sent_headers &&
614 (stream.state == STREAMING_HTTP || stream.state == STREAMING_WAIT || stream.state == STREAMING_BUFFERING)) {
615 header_len = stream.header_len;
616 memcpy(header, stream.header, header_len);
617 _sendRESP = true;
618 stream.sent_headers = true;
619 }
620 if (stream.meta_send) {
621 header_len = stream.header_len;
622 memcpy(header, stream.header, header_len);
623 _sendMETA = true;
624 stream.meta_send = false;
625 }
626 UNLOCK_S;
627
628 LOCK_D;
629 if ((status.stream_state == STREAMING_HTTP || status.stream_state == STREAMING_FILE) && !sentSTMl
630 && decode.state == DECODE_READY) {
631 if (autostart == 0) {
632 decode.state = DECODE_RUNNING;
633 _sendSTMl = true;
634 sentSTMl = true;
635 } else if (autostart == 1) {
636 decode.state = DECODE_RUNNING;
637 _start_output = true;
638 }
639 // autostart 2 and 3 require cont to be received first
640 }
641 if (decode.state == DECODE_COMPLETE || decode.state == DECODE_ERROR) {
642 if (decode.state == DECODE_COMPLETE) _sendSTMd = true;
643 if (decode.state == DECODE_ERROR) _sendSTMn = true;
644 decode.state = DECODE_STOPPED;
645 if (status.stream_state == STREAMING_HTTP || status.stream_state == STREAMING_FILE) {
646 _stream_disconnect = true;
647 }
648 }
649 _decode_state = decode.state;
650 UNLOCK_D;
651
652 LOCK_O;
653 status.output_full = _buf_used(outputbuf);
654 status.output_size = outputbuf->size;
655 status.frames_played = output.frames_played_dmp;
656 status.current_sample_rate = output.current_sample_rate;
657 status.updated = output.updated;
658 status.device_frames = output.device_frames;
659
660 if (output.track_started) {
661 _sendSTMs = true;
662 output.track_started = false;
663 status.stream_start = output.track_start_time;
664 }
665 #if PORTAUDIO
666 if (output.pa_reopen) {
667 _pa_open();
668 output.pa_reopen = false;
669 }
670 #endif
671 if (_start_output && (output.state == OUTPUT_STOPPED || OUTPUT_OFF)) {
672 output.state = OUTPUT_BUFFER;
673 }
674 if (output.state == OUTPUT_RUNNING && !sentSTMu && status.output_full == 0 && status.stream_state <= DISCONNECT &&
675 _decode_state == DECODE_STOPPED) {
676 _sendSTMu = true;
677 sentSTMu = true;
678 LOG_DEBUG("output underrun");
679 output.state = OUTPUT_STOPPED;
680 output.stop_time = now;
681 }
682 if (output.state == OUTPUT_RUNNING && !sentSTMo && status.output_full == 0 && status.stream_state == STREAMING_HTTP) {
683 _sendSTMo = true;
684 sentSTMo = true;
685 }
686 if (output.state == OUTPUT_STOPPED && output.idle_to && (now - output.stop_time > output.idle_to)) {
687 output.state = OUTPUT_OFF;
688 LOG_DEBUG("output timeout");
689 }
690 if (output.state == OUTPUT_RUNNING && now - status.last > 1000) {
691 _sendSTMt = true;
692 status.last = now;
693 }
694 UNLOCK_O;
695
696 #if IR
697 LOCK_I;
698 if (ir.code) {
699 _sendIR = true;
700 ir_code = ir.code;
701 ir_ts = ir.ts;
702 ir.code = 0;
703 }
704 UNLOCK_I;
705 #endif
706
707 if (_stream_disconnect) stream_disconnect();
708
709 // send packets once locks released as packet sending can block
710 if (_sendDSCO) sendDSCO(disconnect_code);
711 if (_sendSTMs) sendSTAT("STMs", 0);
712 if (_sendSTMd) sendSTAT("STMd", 0);
713 if (_sendSTMt) sendSTAT("STMt", 0);
714 if (_sendSTMl) sendSTAT("STMl", 0);
715 if (_sendSTMu) sendSTAT("STMu", 0);
716 if (_sendSTMo) sendSTAT("STMo", 0);
717 if (_sendSTMn) sendSTAT("STMn", 0);
718 if (_sendRESP) sendRESP(header, header_len);
719 if (_sendMETA) sendMETA(header, header_len);
720 #if IR
721 if (_sendIR) sendIR(ir_code, ir_ts);
722 #endif
723 }
724 }
725 }
726
727 // called from other threads to wake state machine above
728 void wake_controller(void) {
729 wake_signal(wake_e);
730 }
731
732 in_addr_t discover_server(void) {
733 struct sockaddr_in d;
734 struct sockaddr_in s;
735 char *buf;
736 struct pollfd pollinfo;
737
738 int disc_sock = socket(AF_INET, SOCK_DGRAM, 0);
739
740 socklen_t enable = 1;
741 setsockopt(disc_sock, SOL_SOCKET, SO_BROADCAST, (const void *)&enable, sizeof(enable));
742
743 buf = "e";
744
745 memset(&d, 0, sizeof(d));
746 d.sin_family = AF_INET;
747 d.sin_port = htons(PORT);
748 d.sin_addr.s_addr = htonl(INADDR_BROADCAST);
749
750 pollinfo.fd = disc_sock;
751 pollinfo.events = POLLIN;
752
753 do {
754
755 LOG_INFO("sending discovery");
756 memset(&s, 0, sizeof(s));
757
758 if (sendto(disc_sock, buf, 1, 0, (struct sockaddr *)&d, sizeof(d)) < 0) {
759 LOG_INFO("error sending disovery");
760 }
761
762 if (poll(&pollinfo, 1, 5000) == 1) {
763 char readbuf[10];
764 socklen_t slen = sizeof(s);
765 recvfrom(disc_sock, readbuf, 10, 0, (struct sockaddr *)&s, &slen);
766 LOG_INFO("got response from: %s:%d", inet_ntoa(s.sin_addr), ntohs(s.sin_port));
767 }
768
769 } while (s.sin_addr.s_addr == 0 && running);
770
771 closesocket(disc_sock);
772
773 return s.sin_addr.s_addr;
774 }
775
776 #define FIXED_CAP_LEN 256
777 #define VAR_CAP_LEN 128
778
779 void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname) {
780 struct sockaddr_in serv_addr;
781 static char fixed_cap[FIXED_CAP_LEN], var_cap[VAR_CAP_LEN] = "";
782 bool reconnect = false;
783 unsigned failed_connect = 0;
784 unsigned slimproto_port = 0;
785 int i;
786
787 wake_create(wake_e);
788
789 loglevel = level;
790 running = true;
791
792 if (server) {
793 server_addr(server, &slimproto_ip, &slimproto_port);
794 }
795
796 if (!slimproto_ip) {
797 slimproto_ip = discover_server();
798 }
799
800 if (!slimproto_port) {
801 slimproto_port = PORT;
802 }
803
804 if (name) {
805 strncpy(player_name, name, PLAYER_NAME_LEN);
806 player_name[PLAYER_NAME_LEN] = '\0';
807 }
808
809 if (namefile) {
810 FILE *fp;
811 name_file = namefile;
812 fp = fopen(namefile, "r");
813 if (fp) {
814 if (!fgets(player_name, PLAYER_NAME_LEN, fp)) {
815 player_name[PLAYER_NAME_LEN] = '\0';
816 } else {
817 // strip any \n from fgets response
818 int len = strlen(player_name);
819 if (len > 0 && player_name[len - 1] == '\n') {
820 player_name[len - 1] = '\0';
821 }
822 LOG_INFO("retrieved name %s from %s", player_name, name_file);
823 }
824 fclose(fp);
825 }
826 }
827
828 if (!running) return;
829
830 LOCK_O;
831 snprintf(fixed_cap, FIXED_CAP_LEN, ",ModelName=%s,MaxSampleRate=%u", modelname ? modelname : MODEL_NAME_STRING,
832 output.supported_rates[0]);
833
834 for (i = 0; i < MAX_CODECS; i++) {
835 if (codecs[i] && codecs[i]->id && strlen(fixed_cap) < FIXED_CAP_LEN - 10) {
836 strcat(fixed_cap, ",");
837 strcat(fixed_cap, codecs[i]->types);
838 }
839 }
840 UNLOCK_O;
841
842 memset(&serv_addr, 0, sizeof(serv_addr));
843 serv_addr.sin_family = AF_INET;
844 serv_addr.sin_addr.s_addr = slimproto_ip;
845 serv_addr.sin_port = htons(slimproto_port);
846
847 LOG_INFO("connecting to %s:%d", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
848
849 new_server = 0;
850
851 while (running) {
852
853 if (new_server) {
854 slimproto_ip = serv_addr.sin_addr.s_addr = new_server;
855 LOG_INFO("switching server to %s:%d", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
856 new_server = 0;
857 reconnect = false;
858 }
859
860 sock = socket(AF_INET, SOCK_STREAM, 0);
861
862 set_nonblock(sock);
863 set_nosigpipe(sock);
864
865 if (connect_timeout(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr), 5) != 0) {
866
867 LOG_INFO("unable to connect to server %u", failed_connect);
868 sleep(5);
869
870 // rediscover server if it was not set at startup
871 if (!server && ++failed_connect > 5) {
872 slimproto_ip = serv_addr.sin_addr.s_addr = discover_server();
873 }
874
875 } else {
876
877 struct sockaddr_in our_addr;
878 socklen_t len;
879
880 LOG_INFO("connected");
881
882 var_cap[0] = '\0';
883 failed_connect = 0;
884
885 // check if this is a local player now we are connected & signal to server via 'loc' format
886 // this requires LocalPlayer server plugin to enable direct file access
887 len = sizeof(our_addr);
888 getsockname(sock, (struct sockaddr *) &our_addr, &len);
889
890 if (our_addr.sin_addr.s_addr == serv_addr.sin_addr.s_addr) {
891 LOG_INFO("local player");
892 strcat(var_cap, ",loc");
893 }
894
895 // add on any capablity to be sent to the new server
896 if (new_server_cap) {
897 strcat(var_cap, new_server_cap);
898 free(new_server_cap);
899 new_server_cap = NULL;
900 }
901
902 sendHELO(reconnect, fixed_cap, var_cap, mac);
903
904 slimproto_run();
905
906 if (!reconnect) {
907 reconnect = true;
908 }
909
910 usleep(100000);
911 }
912
913 closesocket(sock);
914 }
915 }
916
917 void slimproto_stop(void) {
918 LOG_INFO("slimproto stop");
919 running = false;
920 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // packet formats for slimproto
21
22 #pragma pack(push, 1)
23
24 // from S:N:Slimproto _hello_handler
25 struct HELO_packet {
26 char opcode[4];
27 u32_t length;
28 u8_t deviceid;
29 u8_t revision;
30 u8_t mac[6];
31 u8_t uuid[16];
32 u16_t wlan_channellist;
33 u32_t bytes_received_H, bytes_received_L;
34 char lang[2];
35 // u8_t capabilities[];
36 };
37
38 // S:N:Slimproto _stat_handler
39 struct STAT_packet {
40 char opcode[4];
41 u32_t length;
42 u32_t event;
43 u8_t num_crlf;
44 u8_t mas_initialized;
45 u8_t mas_mode;
46 u32_t stream_buffer_size;
47 u32_t stream_buffer_fullness;
48 u32_t bytes_received_H;
49 u32_t bytes_received_L;
50 u16_t signal_strength;
51 u32_t jiffies;
52 u32_t output_buffer_size;
53 u32_t output_buffer_fullness;
54 u32_t elapsed_seconds;
55 u16_t voltage;
56 u32_t elapsed_milliseconds;
57 u32_t server_timestamp;
58 u16_t error_code;
59 };
60
61 // S:N:Slimproto _disco_handler
62 struct DSCO_packet {
63 char opcode[4];
64 u32_t length;
65 u8_t reason;
66 };
67
68 // S:N:Slimproto _http_response_handler
69 struct RESP_header {
70 char opcode[4];
71 u32_t length;
72 // char header[] - added in sendRESP
73 };
74
75 // S:N:Slimproto _http_metadata_handler
76 struct META_header {
77 char opcode[4];
78 u32_t length;
79 // char metadata[]
80 };
81
82 // S:N:Slimproto _http_setting_handler
83 struct SETD_header {
84 char opcode[4];
85 u32_t length;
86 u8_t id;
87 // data
88 };
89
90 #if IR
91 struct IR_packet {
92 char opcode[4];
93 u32_t length;
94 u32_t jiffies;
95 u8_t format; // ignored by server
96 u8_t bits; // ignored by server
97 u32_t ir_code;
98 };
99 #endif
100
101 // from S:P:Squeezebox stream_s
102 struct strm_packet {
103 char opcode[4];
104 char command;
105 u8_t autostart;
106 u8_t format;
107 u8_t pcm_sample_size;
108 u8_t pcm_sample_rate;
109 u8_t pcm_channels;
110 u8_t pcm_endianness;
111 u8_t threshold;
112 u8_t spdif_enable;
113 u8_t transition_period;
114 u8_t transition_type;
115 u8_t flags;
116 u8_t output_threshold;
117 u8_t slaves;
118 u32_t replay_gain;
119 u16_t server_port;
120 u32_t server_ip;
121 //char request_string[];
122 };
123
124 // S:P:Squeezebox2
125 struct aude_packet {
126 char opcode[4];
127 u8_t enable_spdif;
128 u8_t enable_dac;
129 };
130
131 // S:P:Squeezebox2
132 struct audg_packet {
133 char opcode[4];
134 u32_t old_gainL; // unused
135 u32_t old_gainR; // unused
136 u8_t adjust;
137 u8_t preamp; // unused
138 u32_t gainL;
139 u32_t gainR;
140 // squence ids - unused
141 };
142
143 // S:P:Squeezebox2
144 struct cont_packet {
145 char opcode[4];
146 u32_t metaint;
147 u8_t loop;
148 // guids we don't use
149 };
150
151 // S:C:Commands
152 struct serv_packet {
153 char opcode[4];
154 u32_t server_ip;
155 // possible sync group
156 };
157
158 // S:P:Squeezebox2
159 struct setd_packet {
160 char opcode[4];
161 u8_t id;
162 char data[];
163 };
164
165 // codec open - this is an extension to slimproto to allow the server to read the header and then return decode params
166 struct codc_packet {
167 char opcode[4];
168 u8_t format;
169 u8_t pcm_sample_size;
170 u8_t pcm_sample_rate;
171 u8_t pcm_channels;
172 u8_t pcm_endianness;
173 };
174
175 #pragma pack(pop)
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // make may define: PORTAUDIO, SELFPIPE, RESAMPLE, RESAMPLE_MP, VISEXPORT, IR, DSD, LINKALL to influence build
21
22 #define VERSION "v1.8"
23
24 #if !defined(MODEL_NAME)
25 #define MODEL_NAME SqueezeLite
26 #endif
27
28 #define QUOTE(name) #name
29 #define STR(macro) QUOTE(macro)
30 #define MODEL_NAME_STRING STR(MODEL_NAME)
31
32 // build detection
33 #if defined(linux)
34 #define LINUX 1
35 #define OSX 0
36 #define WIN 0
37 #define FREEBSD 0
38 #elif defined (__APPLE__)
39 #define LINUX 0
40 #define OSX 1
41 #define WIN 0
42 #define FREEBSD 0
43 #elif defined (_MSC_VER)
44 #define LINUX 0
45 #define OSX 0
46 #define WIN 1
47 #define FREEBSD 0
48 #elif defined(__FreeBSD__)
49 #define LINUX 0
50 #define OSX 0
51 #define WIN 0
52 #define FREEBSD 1
53 #else
54 #error unknown target
55 #endif
56
57 #if LINUX && !defined(PORTAUDIO)
58 #define ALSA 1
59 #define PORTAUDIO 0
60 #else
61 #define ALSA 0
62 #define PORTAUDIO 1
63 #endif
64
65 #if LINUX && !defined(SELFPIPE)
66 #define EVENTFD 1
67 #define SELFPIPE 0
68 #define WINEVENT 0
69 #endif
70 #if (LINUX && !EVENTFD) || OSX || FREEBSD
71 #define EVENTFD 0
72 #define SELFPIPE 1
73 #define WINEVENT 0
74 #endif
75 #if WIN
76 #define EVENTFD 0
77 #define SELFPIPE 0
78 #define WINEVENT 1
79 #endif
80
81 #if defined(RESAMPLE) || defined(RESAMPLE_MP)
82 #undef RESAMPLE
83 #define RESAMPLE 1 // resampling
84 #define PROCESS 1 // any sample processing (only resampling at present)
85 #else
86 #define RESAMPLE 0
87 #define PROCESS 0
88 #endif
89 #if defined(RESAMPLE_MP)
90 #undef RESAMPLE_MP
91 #define RESAMPLE_MP 1
92 #else
93 #define RESAMPLE_MP 0
94 #endif
95
96 #if defined(FFMPEG)
97 #undef FFMPEG
98 #define FFMPEG 1
99 #else
100 #define FFMPEG 0
101 #endif
102
103 #if LINUX && defined(VISEXPORT)
104 #undef VISEXPORT
105 #define VISEXPORT 1 // visulizer export support uses linux shared memory
106 #else
107 #define VISEXPORT 0
108 #endif
109
110 #if LINUX && defined(IR)
111 #undef IR
112 #define IR 1
113 #else
114 #define IR 0
115 #endif
116
117 #if defined(DSD)
118 #undef DSD
119 #define DSD 1
120 #define IF_DSD(x) { x }
121 #else
122 #undef DSD
123 #define DSD 0
124 #define IF_DSD(x)
125 #endif
126
127 #if defined(LINKALL)
128 #undef LINKALL
129 #define LINKALL 1 // link all libraries at build time - requires all to be available at run time
130 #else
131 #define LINKALL 0
132 #endif
133
134
135 #if !LINKALL
136
137 // dynamically loaded libraries at run time
138
139 #if LINUX
140 #define LIBFLAC "libFLAC.so.8"
141 #define LIBMAD "libmad.so.0"
142 #define LIBMPG "libmpg123.so.0"
143 #define LIBVORBIS "libvorbisfile.so.3"
144 #define LIBTREMOR "libvorbisidec.so.1"
145 #define LIBFAAD "libfaad.so.2"
146 #define LIBAVUTIL "libavutil.so.%d"
147 #define LIBAVCODEC "libavcodec.so.%d"
148 #define LIBAVFORMAT "libavformat.so.%d"
149 #define LIBSOXR "libsoxr.so.0"
150 #define LIBLIRC "liblirc_client.so.0"
151 #endif
152
153 #if OSX
154 #define LIBFLAC "libFLAC.8.dylib"
155 #define LIBMAD "libmad.0.dylib"
156 #define LIBMPG "libmpg123.0.dylib"
157 #define LIBVORBIS "libvorbisfile.3.dylib"
158 #define LIBTREMOR "libvorbisidec.1.dylib"
159 #define LIBFAAD "libfaad.2.dylib"
160 #define LIBAVUTIL "libavutil.%d.dylib"
161 #define LIBAVCODEC "libavcodec.%d.dylib"
162 #define LIBAVFORMAT "libavformat.%d.dylib"
163 #define LIBSOXR "libsoxr.0.dylib"
164 #endif
165
166 #if WIN
167 #define LIBFLAC "libFLAC.dll"
168 #define LIBMAD "libmad-0.dll"
169 #define LIBMPG "libmpg123-0.dll"
170 #define LIBVORBIS "libvorbisfile.dll"
171 #define LIBTREMOR "libvorbisidec.dll"
172 #define LIBFAAD "libfaad2.dll"
173 #define LIBAVUTIL "avutil-%d.dll"
174 #define LIBAVCODEC "avcodec-%d.dll"
175 #define LIBAVFORMAT "avformat-%d.dll"
176 #define LIBSOXR "libsoxr.dll"
177 #endif
178
179 #if FREEBSD
180 #define LIBFLAC "libFLAC.so.11"
181 #define LIBMAD "libmad.so.2"
182 #define LIBMPG "libmpg123.so.0"
183 #define LIBVORBIS "libvorbisfile.so.6"
184 #define LIBTREMOR "libvorbisidec.so.1"
185 #define LIBFAAD "libfaad.so.2"
186 #define LIBAVUTIL "libavutil.so.%d"
187 #define LIBAVCODEC "libavcodec.so.%d"
188 #define LIBAVFORMAT "libavformat.so.%d"
189 #endif
190
191 #endif // !LINKALL
192
193 // config options
194 #define STREAMBUF_SIZE (2 * 1024 * 1024)
195 #define OUTPUTBUF_SIZE (44100 * 8 * 10)
196 #define OUTPUTBUF_SIZE_CROSSFADE (OUTPUTBUF_SIZE * 12 / 10)
197
198 #define MAX_HEADER 4096 // do not reduce as icy-meta max is 4080
199
200 #if ALSA
201 #define ALSA_BUFFER_TIME 40
202 #define ALSA_PERIOD_COUNT 4
203 #define OUTPUT_RT_PRIORITY 45
204 #endif
205
206 #define SL_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
207
208 #include <stdio.h>
209 #include <stdlib.h>
210 #include <stdarg.h>
211 #include <string.h>
212 #include <errno.h>
213 #include <limits.h>
214 #include <sys/types.h>
215
216 #if LINUX || OSX || FREEBSD
217 #include <unistd.h>
218 #include <stdbool.h>
219 #include <netinet/in.h>
220 #include <arpa/inet.h>
221 #include <sys/time.h>
222 #include <sys/socket.h>
223 #include <poll.h>
224 #include <dlfcn.h>
225 #include <pthread.h>
226 #include <signal.h>
227
228 #define STREAM_THREAD_STACK_SIZE 64 * 1024
229 #define DECODE_THREAD_STACK_SIZE 128 * 1024
230 #define OUTPUT_THREAD_STACK_SIZE 64 * 1024
231 #define IR_THREAD_STACK_SIZE 64 * 1024
232 #define thread_t pthread_t;
233 #define closesocket(s) close(s)
234 #define last_error() errno
235 #define ERROR_WOULDBLOCK EWOULDBLOCK
236
237 typedef u_int8_t u8_t;
238 typedef u_int16_t u16_t;
239 typedef u_int32_t u32_t;
240 typedef u_int64_t u64_t;
241 typedef int16_t s16_t;
242 typedef int32_t s32_t;
243 typedef int64_t s64_t;
244
245 #define mutex_type pthread_mutex_t
246 #define mutex_create(m) pthread_mutex_init(&m, NULL)
247 #define mutex_create_p(m) pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); pthread_mutex_init(&m, &attr); pthread_mutexattr_destroy(&attr)
248 #define mutex_lock(m) pthread_mutex_lock(&m)
249 #define mutex_unlock(m) pthread_mutex_unlock(&m)
250 #define mutex_destroy(m) pthread_mutex_destroy(&m)
251 #define thread_type pthread_t
252
253 #endif
254
255 #if WIN
256
257 #include <winsock2.h>
258 #include <ws2tcpip.h>
259 #include <io.h>
260
261 #define STREAM_THREAD_STACK_SIZE (1024 * 64)
262 #define DECODE_THREAD_STACK_SIZE (1024 * 128)
263 #define OUTPUT_THREAD_STACK_SIZE (1024 * 64)
264
265 typedef unsigned __int8 u8_t;
266 typedef unsigned __int16 u16_t;
267 typedef unsigned __int32 u32_t;
268 typedef unsigned __int64 u64_t;
269 typedef __int16 s16_t;
270 typedef __int32 s32_t;
271 typedef __int64 s64_t;
272
273 typedef BOOL bool;
274 #define true TRUE
275 #define false FALSE
276
277 #define inline __inline
278
279 #define mutex_type HANDLE
280 #define mutex_create(m) m = CreateMutex(NULL, FALSE, NULL)
281 #define mutex_create_p mutex_create
282 #define mutex_lock(m) WaitForSingleObject(m, INFINITE)
283 #define mutex_unlock(m) ReleaseMutex(m)
284 #define mutex_destroy(m) CloseHandle(m)
285 #define thread_type HANDLE
286
287 #define usleep(x) Sleep(x/1000)
288 #define sleep(x) Sleep(x*1000)
289 #define last_error() WSAGetLastError()
290 #define ERROR_WOULDBLOCK WSAEWOULDBLOCK
291 #define open _open
292 #define read _read
293 #define snprintf _snprintf
294
295 #define in_addr_t u32_t
296 #define socklen_t int
297 #define ssize_t int
298
299 #define RTLD_NOW 0
300
301 #endif
302
303 #if !defined(MSG_NOSIGNAL)
304 #define MSG_NOSIGNAL 0
305 #endif
306
307 typedef u32_t frames_t;
308 typedef int sockfd;
309
310 #if EVENTFD
311 #include <sys/eventfd.h>
312 #define event_event int
313 #define event_handle struct pollfd
314 #define wake_create(e) e = eventfd(0, 0)
315 #define wake_signal(e) eventfd_write(e, 1)
316 #define wake_clear(e) eventfd_t val; eventfd_read(e, &val)
317 #define wake_close(e) close(e)
318 #endif
319
320 #if SELFPIPE
321 #define event_handle struct pollfd
322 #define event_event struct wake
323 #define wake_create(e) pipe(e.fds); set_nonblock(e.fds[0]); set_nonblock(e.fds[1])
324 #define wake_signal(e) write(e.fds[1], ".", 1)
325 #define wake_clear(e) char c[10]; read(e, &c, 10)
326 #define wake_close(e) close(e.fds[0]); close(e.fds[1])
327 struct wake {
328 int fds[2];
329 };
330 #endif
331
332 #if WINEVENT
333 #define event_event HANDLE
334 #define event_handle HANDLE
335 #define wake_create(e) e = CreateEvent(NULL, FALSE, FALSE, NULL)
336 #define wake_signal(e) SetEvent(e)
337 #define wake_close(e) CloseHandle(e)
338 #endif
339
340 // printf/scanf formats for u64_t
341 #if (LINUX && __WORDSIZE == 64) || (FREEBSD && __LP64__)
342 #define FMT_u64 "%lu"
343 #define FMT_x64 "%lx"
344 #elif __GLIBC_HAVE_LONG_LONG || defined __GNUC__ || WIN
345 #define FMT_u64 "%llu"
346 #define FMT_x64 "%llx"
347 #else
348 #error can not support u64_t
349 #endif
350
351 #define MAX_SILENCE_FRAMES 2048
352
353 #define FIXED_ONE 0x10000
354
355 #define BYTES_PER_FRAME 8
356
357 #define min(a,b) (((a) < (b)) ? (a) : (b))
358
359 // logging
360 typedef enum { lERROR = 0, lWARN, lINFO, lDEBUG, lSDEBUG } log_level;
361
362 const char *logtime(void);
363 void logprint(const char *fmt, ...);
364
365 #define LOG_ERROR(fmt, ...) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
366 #define LOG_WARN(fmt, ...) if (loglevel >= lWARN) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
367 #define LOG_INFO(fmt, ...) if (loglevel >= lINFO) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
368 #define LOG_DEBUG(fmt, ...) if (loglevel >= lDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
369 #define LOG_SDEBUG(fmt, ...) if (loglevel >= lSDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
370
371 // utils.c (non logging)
372 typedef enum { EVENT_TIMEOUT = 0, EVENT_READ, EVENT_WAKE } event_type;
373
374 char *next_param(char *src, char c);
375 u32_t gettime_ms(void);
376 void get_mac(u8_t *mac);
377 void set_nonblock(sockfd s);
378 int connect_timeout(sockfd sock, const struct sockaddr *addr, socklen_t addrlen, int timeout);
379 void server_addr(char *server, in_addr_t *ip_ptr, unsigned *port_ptr);
380 void set_readwake_handles(event_handle handles[], sockfd s, event_event e);
381 event_type wait_readwake(event_handle handles[], int timeout);
382 void packN(u32_t *dest, u32_t val);
383 void packn(u16_t *dest, u16_t val);
384 u32_t unpackN(u32_t *src);
385 u16_t unpackn(u16_t *src);
386 #if OSX
387 void set_nosigpipe(sockfd s);
388 #else
389 #define set_nosigpipe(s)
390 #endif
391 #if WIN
392 void winsock_init(void);
393 void winsock_close(void);
394 void *dlopen(const char *filename, int flag);
395 void *dlsym(void *handle, const char *symbol);
396 char *dlerror(void);
397 int poll(struct pollfd *fds, unsigned long numfds, int timeout);
398 #endif
399 #if LINUX || FREEBSD
400 void touch_memory(u8_t *buf, size_t size);
401 #endif
402
403 // buffer.c
404 struct buffer {
405 u8_t *buf;
406 u8_t *readp;
407 u8_t *writep;
408 u8_t *wrap;
409 size_t size;
410 size_t base_size;
411 mutex_type mutex;
412 };
413
414 // _* called with mutex locked
415 unsigned _buf_used(struct buffer *buf);
416 unsigned _buf_space(struct buffer *buf);
417 unsigned _buf_cont_read(struct buffer *buf);
418 unsigned _buf_cont_write(struct buffer *buf);
419 void _buf_inc_readp(struct buffer *buf, unsigned by);
420 void _buf_inc_writep(struct buffer *buf, unsigned by);
421 void buf_flush(struct buffer *buf);
422 void buf_adjust(struct buffer *buf, size_t mod);
423 void _buf_resize(struct buffer *buf, size_t size);
424 void buf_init(struct buffer *buf, size_t size);
425 void buf_destroy(struct buffer *buf);
426
427 // slimproto.c
428 void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname);
429 void slimproto_stop(void);
430 void wake_controller(void);
431
432 // stream.c
433 typedef enum { STOPPED = 0, DISCONNECT, STREAMING_WAIT,
434 STREAMING_BUFFERING, STREAMING_FILE, STREAMING_HTTP, SEND_HEADERS, RECV_HEADERS } stream_state;
435 typedef enum { DISCONNECT_OK = 0, LOCAL_DISCONNECT = 1, REMOTE_DISCONNECT = 2, UNREACHABLE = 3, TIMEOUT = 4 } disconnect_code;
436
437 struct streamstate {
438 stream_state state;
439 disconnect_code disconnect;
440 char *header;
441 size_t header_len;
442 bool sent_headers;
443 bool cont_wait;
444 u64_t bytes;
445 unsigned threshold;
446 u32_t meta_interval;
447 u32_t meta_next;
448 u32_t meta_left;
449 bool meta_send;
450 };
451
452 void stream_init(log_level level, unsigned stream_buf_size);
453 void stream_close(void);
454 void stream_file(const char *header, size_t header_len, unsigned threshold);
455 void stream_sock(u32_t ip, u16_t port, const char *header, size_t header_len, unsigned threshold, bool cont_wait);
456 bool stream_disconnect(void);
457
458 // decode.c
459 typedef enum { DECODE_STOPPED = 0, DECODE_READY, DECODE_RUNNING, DECODE_COMPLETE, DECODE_ERROR } decode_state;
460
461 struct decodestate {
462 decode_state state;
463 bool new_stream;
464 mutex_type mutex;
465 #if PROCESS
466 bool direct;
467 bool process;
468 #endif
469 };
470
471 #if PROCESS
472 struct processstate {
473 u8_t *inbuf, *outbuf;
474 unsigned max_in_frames, max_out_frames;
475 unsigned in_frames, out_frames;
476 unsigned in_sample_rate, out_sample_rate;
477 unsigned long total_in, total_out;
478 };
479 #endif
480
481 struct codec {
482 char id;
483 char *types;
484 unsigned min_read_bytes;
485 unsigned min_space;
486 void (*open)(u8_t sample_size, u8_t sample_rate, u8_t channels, u8_t endianness);
487 void (*close)(void);
488 decode_state (*decode)(void);
489 };
490
491 void decode_init(log_level level, const char *include_codecs, const char *exclude_codecs);
492 void decode_close(void);
493 void decode_flush(void);
494 unsigned decode_newstream(unsigned sample_rate, unsigned supported_rates[]);
495 void codec_open(u8_t format, u8_t sample_size, u8_t sample_rate, u8_t channels, u8_t endianness);
496
497 #if PROCESS
498 // process.c
499 void process_samples(void);
500 void process_drain(void);
501 void process_flush(void);
502 unsigned process_newstream(bool *direct, unsigned raw_sample_rate, unsigned supported_rates[]);
503 void process_init(char *opt);
504 #endif
505
506 #if RESAMPLE
507 // resample.c
508 void resample_samples(struct processstate *process);
509 bool resample_drain(struct processstate *process);
510 bool resample_newstream(struct processstate *process, unsigned raw_sample_rate, unsigned supported_rates[]);
511 void resample_flush(void);
512 bool resample_init(char *opt);
513 #endif
514
515 // output.c output_alsa.c output_pa.c output_pack.c
516 typedef enum { OUTPUT_OFF = -1, OUTPUT_STOPPED = 0, OUTPUT_BUFFER, OUTPUT_RUNNING,
517 OUTPUT_PAUSE_FRAMES, OUTPUT_SKIP_FRAMES, OUTPUT_START_AT } output_state;
518
519 typedef enum { S32_LE, S24_LE, S24_3LE, S16_LE } output_format;
520
521 typedef enum { FADE_INACTIVE = 0, FADE_DUE, FADE_ACTIVE } fade_state;
522 typedef enum { FADE_UP = 1, FADE_DOWN, FADE_CROSS } fade_dir;
523 typedef enum { FADE_NONE = 0, FADE_CROSSFADE, FADE_IN, FADE_OUT, FADE_INOUT } fade_mode;
524
525 #define MAX_SUPPORTED_SAMPLERATES 16
526 #define TEST_RATES = { 384000, 352800, 192000, 176400, 96000, 88200, 48000, 44100, 32000, 24000, 22500, 16000, 12000, 11025, 8000, 0 }
527
528 struct outputstate {
529 output_state state;
530 output_format format;
531 const char *device;
532 #if ALSA
533 unsigned buffer;
534 unsigned period;
535 #endif
536 bool track_started;
537 #if PORTAUDIO
538 bool pa_reopen;
539 unsigned latency;
540 int osx_playnice;
541 #endif
542 int (* write_cb)(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr);
543 unsigned start_frames;
544 unsigned frames_played;
545 unsigned frames_played_dmp;// frames played at the point delay is measured
546 unsigned current_sample_rate;
547 unsigned supported_rates[MAX_SUPPORTED_SAMPLERATES]; // ordered largest first so [0] is max_rate
548 unsigned default_sample_rate;
549 bool error_opening;
550 unsigned device_frames;
551 u32_t updated;
552 u32_t track_start_time;
553 u32_t current_replay_gain;
554 union {
555 u32_t pause_frames;
556 u32_t skip_frames;
557 u32_t start_at;
558 };
559 unsigned next_sample_rate; // set in decode thread
560 u8_t *track_start; // set in decode thread
561 u32_t gainL; // set by slimproto
562 u32_t gainR; // set by slimproto
563 bool invert; // set by slimproto
564 u32_t next_replay_gain; // set by slimproto
565 unsigned threshold; // set by slimproto
566 fade_state fade;
567 u8_t *fade_start;
568 u8_t *fade_end;
569 fade_dir fade_dir;
570 fade_mode fade_mode; // set by slimproto
571 unsigned fade_secs; // set by slimproto
572 unsigned rate_delay;
573 bool delay_active;
574 u32_t stop_time;
575 u32_t idle_to;
576 #if DSD
577 bool next_dop; // set in decode thread
578 bool dop;
579 bool has_dop; // set in dop_init - output device supports dop
580 unsigned dop_delay; // set in dop_init - delay in ms switching to/from dop
581 #endif
582 };
583
584 void output_init_common(log_level level, const char *device, unsigned output_buf_size, unsigned rates[], unsigned idle);
585 void output_close_common(void);
586 void output_flush(void);
587 // _* called with mutex locked
588 frames_t _output_frames(frames_t avail);
589 void _checkfade(bool);
590
591 // output_alsa.c
592 #if ALSA
593 void list_devices(void);
594 void list_mixers(const char *output_device);
595 void set_volume(unsigned left, unsigned right);
596 bool test_open(const char *device, unsigned rates[]);
597 void output_init_alsa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[],
598 unsigned rate_delay, unsigned rt_priority, unsigned idle, char *volume_mixer, bool mixer_unmute);
599 void output_close_alsa(void);
600 #endif
601
602 // output_pa.c
603 #if PORTAUDIO
604 void list_devices(void);
605 void set_volume(unsigned left, unsigned right);
606 bool test_open(const char *device, unsigned rates[]);
607 void output_init_pa(log_level level, const char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle);
608 void output_close_pa(void);
609 void _pa_open(void);
610 #endif
611
612 // output_stdout.c
613 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay);
614 void output_close_stdout(void);
615
616 // output_pack.c
617 void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, output_format format);
618 void _apply_cross(struct buffer *outputbuf, frames_t out_frames, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr);
619 void _apply_gain(struct buffer *outputbuf, frames_t count, s32_t gainL, s32_t gainR);
620 s32_t gain(s32_t gain, s32_t sample);
621 s32_t to_gain(float f);
622
623 // output_vis.c
624 #if VISEXPORT
625 void _vis_export(struct buffer *outputbuf, struct outputstate *output, frames_t out_frames, bool silence);
626 void output_vis_init(log_level level, u8_t *mac);
627 void vis_stop(void);
628 #else
629 #define _vis_export(...)
630 #define vis_stop()
631 #endif
632
633 // dop.c
634 #if DSD
635 bool is_flac_dop(u32_t *lptr, u32_t *rptr, frames_t frames);
636 void update_dop(u32_t *ptr, frames_t frames, bool invert);
637 void dop_silence_frames(u32_t *ptr, frames_t frames);
638 void dop_init(bool enable, unsigned delay);
639 #endif
640
641 // codecs
642 #define MAX_CODECS 9
643
644 struct codec *register_flac(void);
645 struct codec *register_pcm(void);
646 struct codec *register_mad(void);
647 struct codec *register_mpg(void);
648 struct codec *register_vorbis(void);
649 struct codec *register_faad(void);
650 struct codec *register_dsd(void);
651 struct codec *register_ff(const char *codec);
652
653 // ir.c
654 #if IR
655 struct irstate {
656 mutex_type mutex;
657 u32_t code;
658 u32_t ts;
659 };
660
661 void ir_init(log_level level, char *lircrc);
662 void ir_close(void);
663 #endif
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 // stream thread
21
22 #include "squeezelite.h"
23
24 #include <fcntl.h>
25
26 static log_level loglevel;
27
28 static struct buffer buf;
29 struct buffer *streambuf = &buf;
30
31 #define LOCK mutex_lock(streambuf->mutex)
32 #define UNLOCK mutex_unlock(streambuf->mutex)
33
34 static sockfd fd;
35
36 struct streamstate stream;
37
38 static void send_header(void) {
39 char *ptr = stream.header;
40 int len = stream.header_len;
41
42 unsigned try = 0;
43 ssize_t n;
44
45 while (len) {
46 n = send(fd, ptr, len, MSG_NOSIGNAL);
47 if (n <= 0) {
48 if (n < 0 && last_error() == ERROR_WOULDBLOCK && try < 10) {
49 LOG_SDEBUG("retrying (%d) writing to socket", ++try);
50 usleep(1000);
51 continue;
52 }
53 LOG_INFO("failed writing to socket: %s", strerror(last_error()));
54 stream.disconnect = LOCAL_DISCONNECT;
55 stream.state = DISCONNECT;
56 wake_controller();
57 return;
58 }
59 LOG_SDEBUG("wrote %d bytes to socket", n);
60 ptr += n;
61 len -= n;
62 }
63 LOG_SDEBUG("wrote header");
64 }
65
66 static bool running = true;
67
68 static void _disconnect(stream_state state, disconnect_code disconnect) {
69 stream.state = state;
70 stream.disconnect = disconnect;
71 closesocket(fd);
72 fd = -1;
73 wake_controller();
74 }
75
76 static void *stream_thread() {
77
78 while (running) {
79
80 struct pollfd pollinfo;
81 size_t space;
82
83 LOCK;
84
85 space = min(_buf_space(streambuf), _buf_cont_write(streambuf));
86
87 if (fd < 0 || !space || stream.state <= STREAMING_WAIT) {
88 UNLOCK;
89 usleep(100000);
90 continue;
91 }
92
93 if (stream.state == STREAMING_FILE) {
94
95 int n = read(fd, streambuf->writep, space);
96 if (n == 0) {
97 LOG_INFO("end of stream");
98 _disconnect(DISCONNECT, DISCONNECT_OK);
99 }
100 if (n > 0) {
101 _buf_inc_writep(streambuf, n);
102 stream.bytes += n;
103 LOG_SDEBUG("streambuf read %d bytes", n);
104 }
105 if (n < 0) {
106 LOG_WARN("error reading: %s", strerror(last_error()));
107 _disconnect(DISCONNECT, REMOTE_DISCONNECT);
108 }
109
110 UNLOCK;
111 continue;
112
113 } else {
114
115 pollinfo.fd = fd;
116 pollinfo.events = POLLIN;
117 if (stream.state == SEND_HEADERS) {
118 pollinfo.events |= POLLOUT;
119 }
120 }
121
122 UNLOCK;
123
124 if (poll(&pollinfo, 1, 100)) {
125
126 LOCK;
127
128 // check socket has not been closed while in poll
129 if (fd < 0) {
130 UNLOCK;
131 continue;
132 }
133
134 if ((pollinfo.revents & POLLOUT) && stream.state == SEND_HEADERS) {
135 send_header();
136 stream.header_len = 0;
137 stream.state = RECV_HEADERS;
138 UNLOCK;
139 continue;
140 }
141
142 if (pollinfo.revents & (POLLIN | POLLHUP)) {
143
144 // get response headers
145 if (stream.state == RECV_HEADERS) {
146
147 // read one byte at a time to catch end of header
148 char c;
149 static int endtok;
150
151 int n = recv(fd, &c, 1, 0);
152 if (n <= 0) {
153 if (n < 0 && last_error() == ERROR_WOULDBLOCK) {
154 UNLOCK;
155 continue;
156 }
157 LOG_INFO("error reading headers: %s", n ? strerror(last_error()) : "closed");
158 _disconnect(STOPPED, LOCAL_DISCONNECT);
159 UNLOCK;
160 continue;
161 }
162
163 *(stream.header + stream.header_len) = c;
164 stream.header_len++;
165
166 if (stream.header_len > MAX_HEADER - 1) {
167 LOG_ERROR("received headers too long: %u", stream.header_len);
168 _disconnect(DISCONNECT, LOCAL_DISCONNECT);
169 }
170
171 if (stream.header_len > 1 && (c == '\r' || c == '\n')) {
172 endtok++;
173 if (endtok == 4) {
174 *(stream.header + stream.header_len) = '\0';
175 LOG_INFO("headers: len: %d\n%s", stream.header_len, stream.header);
176 stream.state = stream.cont_wait ? STREAMING_WAIT : STREAMING_BUFFERING;
177 wake_controller();
178 }
179 } else {
180 endtok = 0;
181 }
182
183 UNLOCK;
184 continue;
185 }
186
187 // receive icy meta data
188 if (stream.meta_interval && stream.meta_next == 0) {
189
190 if (stream.meta_left == 0) {
191 // read meta length
192 u8_t c;
193 int n = recv(fd, &c, 1, 0);
194 if (n <= 0) {
195 if (n < 0 && last_error() == ERROR_WOULDBLOCK) {
196 UNLOCK;
197 continue;
198 }
199 LOG_INFO("error reading icy meta: %s", n ? strerror(last_error()) : "closed");
200 _disconnect(STOPPED, LOCAL_DISCONNECT);
201 UNLOCK;
202 continue;
203 }
204 stream.meta_left = 16 * c;
205 stream.header_len = 0; // amount of received meta data
206 // MAX_HEADER must be more than meta max of 16 * 255
207 }
208
209 if (stream.meta_left) {
210 int n = recv(fd, stream.header + stream.header_len, stream.meta_left, 0);
211 if (n <= 0) {
212 if (n < 0 && last_error() == ERROR_WOULDBLOCK) {
213 UNLOCK;
214 continue;
215 }
216 LOG_INFO("error reading icy meta: %s", n ? strerror(last_error()) : "closed");
217 _disconnect(STOPPED, LOCAL_DISCONNECT);
218 UNLOCK;
219 continue;
220 }
221 stream.meta_left -= n;
222 stream.header_len += n;
223 }
224
225 if (stream.meta_left == 0) {
226 if (stream.header_len) {
227 *(stream.header + stream.header_len) = '\0';
228 LOG_INFO("icy meta: len: %u\n%s", stream.header_len, stream.header);
229 stream.meta_send = true;
230 wake_controller();
231 }
232 stream.meta_next = stream.meta_interval;
233 UNLOCK;
234 continue;
235 }
236
237 // stream body into streambuf
238 } else {
239 int n;
240
241 space = min(_buf_space(streambuf), _buf_cont_write(streambuf));
242 if (stream.meta_interval) {
243 space = min(space, stream.meta_next);
244 }
245
246 n = recv(fd, streambuf->writep, space, 0);
247 if (n == 0) {
248 LOG_INFO("end of stream");
249 _disconnect(DISCONNECT, DISCONNECT_OK);
250 }
251 if (n < 0 && last_error() != ERROR_WOULDBLOCK) {
252 LOG_INFO("error reading: %s", strerror(last_error()));
253 _disconnect(DISCONNECT, REMOTE_DISCONNECT);
254 }
255
256 if (n > 0) {
257 _buf_inc_writep(streambuf, n);
258 stream.bytes += n;
259 if (stream.meta_interval) {
260 stream.meta_next -= n;
261 }
262 }
263
264 if (stream.state == STREAMING_BUFFERING && stream.bytes > stream.threshold) {
265 stream.state = STREAMING_HTTP;
266 wake_controller();
267 }
268
269 LOG_SDEBUG("streambuf read %d bytes", n);
270 }
271 }
272
273 UNLOCK;
274
275 } else {
276
277 LOG_SDEBUG("poll timeout");
278 }
279 }
280
281 return 0;
282 }
283
284 static thread_type thread;
285
286 void stream_init(log_level level, unsigned stream_buf_size) {
287 loglevel = level;
288
289 LOG_INFO("init stream");
290 LOG_DEBUG("streambuf size: %u", stream_buf_size);
291
292 buf_init(streambuf, stream_buf_size);
293 if (streambuf->buf == NULL) {
294 LOG_ERROR("unable to malloc buffer");
295 exit(0);
296 }
297
298 stream.state = STOPPED;
299 stream.header = malloc(MAX_HEADER);
300 *stream.header = '\0';
301
302 fd = -1;
303
304 #if LINUX || FREEBSD
305 touch_memory(streambuf->buf, streambuf->size);
306 #endif
307
308 #if LINUX || OSX || FREEBSD
309 pthread_attr_t attr;
310 pthread_attr_init(&attr);
311 pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + STREAM_THREAD_STACK_SIZE);
312 pthread_create(&thread, &attr, stream_thread, NULL);
313 pthread_attr_destroy(&attr);
314 #endif
315 #if WIN
316 thread = CreateThread(NULL, STREAM_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&stream_thread, NULL, 0, NULL);
317 #endif
318 }
319
320 void stream_close(void) {
321 LOG_INFO("close stream");
322 LOCK;
323 running = false;
324 UNLOCK;
325 #if LINUX || OSX || FREEBSD
326 pthread_join(thread, NULL);
327 #endif
328 free(stream.header);
329 buf_destroy(streambuf);
330 }
331
332 void stream_file(const char *header, size_t header_len, unsigned threshold) {
333 buf_flush(streambuf);
334
335 LOCK;
336
337 stream.header_len = header_len;
338 memcpy(stream.header, header, header_len);
339 *(stream.header+header_len) = '\0';
340
341 LOG_INFO("opening local file: %s", stream.header);
342
343 #if WIN
344 fd = open(stream.header, O_RDONLY | O_BINARY);
345 #else
346 fd = open(stream.header, O_RDONLY);
347 #endif
348
349 stream.state = STREAMING_FILE;
350 if (fd < 0) {
351 LOG_INFO("can't open file: %s", stream.header);
352 stream.state = DISCONNECT;
353 }
354 wake_controller();
355
356 stream.cont_wait = false;
357 stream.meta_interval = 0;
358 stream.meta_next = 0;
359 stream.meta_left = 0;
360 stream.meta_send = false;
361 stream.sent_headers = false;
362 stream.bytes = 0;
363 stream.threshold = threshold;
364
365 UNLOCK;
366 }
367
368 void stream_sock(u32_t ip, u16_t port, const char *header, size_t header_len, unsigned threshold, bool cont_wait) {
369 struct sockaddr_in addr;
370
371 int sock = socket(AF_INET, SOCK_STREAM, 0);
372
373 if (sock < 0) {
374 LOG_ERROR("failed to create socket");
375 return;
376 }
377
378 memset(&addr, 0, sizeof(addr));
379 addr.sin_family = AF_INET;
380 addr.sin_addr.s_addr = ip;
381 addr.sin_port = port;
382
383 LOG_INFO("connecting to %s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
384
385 set_nonblock(sock);
386 set_nosigpipe(sock);
387
388 if (connect_timeout(sock, (struct sockaddr *) &addr, sizeof(addr), 10) < 0) {
389 LOG_INFO("unable to connect to server");
390 LOCK;
391 stream.state = DISCONNECT;
392 stream.disconnect = UNREACHABLE;
393 UNLOCK;
394 return;
395 }
396
397 buf_flush(streambuf);
398
399 LOCK;
400
401 fd = sock;
402 stream.state = SEND_HEADERS;
403 stream.cont_wait = cont_wait;
404 stream.meta_interval = 0;
405 stream.meta_next = 0;
406 stream.meta_left = 0;
407 stream.meta_send = false;
408 stream.header_len = header_len;
409 memcpy(stream.header, header, header_len);
410 *(stream.header+header_len) = '\0';
411
412 LOG_INFO("header: %s", stream.header);
413
414 stream.sent_headers = false;
415 stream.bytes = 0;
416 stream.threshold = threshold;
417
418 UNLOCK;
419 }
420
421 bool stream_disconnect(void) {
422 bool disc = false;
423 LOCK;
424 if (fd != -1) {
425 closesocket(fd);
426 fd = -1;
427 disc = true;
428 }
429 stream.state = STOPPED;
430 UNLOCK;
431 return disc;
432 }
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 #if LINUX || OSX || FREEBSD
23 #include <sys/ioctl.h>
24 #include <net/if.h>
25 #include <netdb.h>
26 #if FREEBSD
27 #include <ifaddrs.h>
28 #include <net/if_dl.h>
29 #include <net/if_types.h>
30 #endif
31 #endif
32 #if WIN
33 #include <iphlpapi.h>
34 #endif
35 #if OSX
36 #include <net/if_dl.h>
37 #include <net/if_types.h>
38 #include <ifaddrs.h>
39 #include <netdb.h>
40 #endif
41
42 #include <fcntl.h>
43
44 // logging functions
45 const char *logtime(void) {
46 static char buf[100];
47 #if WIN
48 SYSTEMTIME lt;
49 GetLocalTime(&lt);
50 sprintf(buf, "[%02d:%02d:%02d.%03d]", lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
51 #else
52 struct timeval tv;
53 gettimeofday(&tv, NULL);
54 strftime(buf, sizeof(buf), "[%T.", localtime(&tv.tv_sec));
55 sprintf(buf+strlen(buf), "%06ld]", (long)tv.tv_usec);
56 #endif
57 return buf;
58 }
59
60 void logprint(const char *fmt, ...) {
61 va_list args;
62 va_start(args, fmt);
63 vfprintf(stderr, fmt, args);
64 fflush(stderr);
65 }
66
67 // cmdline parsing
68 char *next_param(char *src, char c) {
69 static char *str = NULL;
70 char *ptr, *ret;
71 if (src) str = src;
72 if (str && (ptr = strchr(str, c))) {
73 ret = str;
74 *ptr = '\0';
75 str = ptr + 1;
76 } else {
77 ret = str;
78 str = NULL;
79 }
80
81 return ret && ret[0] ? ret : NULL;
82 }
83
84 // clock
85 u32_t gettime_ms(void) {
86 #if WIN
87 return GetTickCount();
88 #else
89 #if LINUX || FREEBSD
90 struct timespec ts;
91 if (!clock_gettime(CLOCK_MONOTONIC, &ts)) {
92 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
93 }
94 #endif
95 struct timeval tv;
96 gettimeofday(&tv, NULL);
97 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
98 #endif
99 }
100
101 // mac address
102 #if LINUX
103 // search first 4 interfaces returned by IFCONF
104 void get_mac(u8_t mac[]) {
105 struct ifconf ifc;
106 struct ifreq *ifr, *ifend;
107 struct ifreq ifreq;
108 struct ifreq ifs[4];
109
110 mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
111
112 int s = socket(AF_INET, SOCK_DGRAM, 0);
113
114 ifc.ifc_len = sizeof(ifs);
115 ifc.ifc_req = ifs;
116
117 if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
118 ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
119
120 for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
121 if (ifr->ifr_addr.sa_family == AF_INET) {
122
123 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
124 if (ioctl (s, SIOCGIFHWADDR, &ifreq) == 0) {
125 memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);
126 if (mac[0]+mac[1]+mac[2] != 0) {
127 break;
128 }
129 }
130 }
131 }
132 }
133
134 close(s);
135 }
136 #endif
137
138 #if OSX || FREEBSD
139 void get_mac(u8_t mac[]) {
140 struct ifaddrs *addrs, *ptr;
141 const struct sockaddr_dl *dlAddr;
142 const unsigned char *base;
143
144 mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
145
146 if (getifaddrs(&addrs) == 0) {
147 ptr = addrs;
148 while (ptr) {
149 if (ptr->ifa_addr->sa_family == AF_LINK && ((const struct sockaddr_dl *) ptr->ifa_addr)->sdl_type == IFT_ETHER) {
150 dlAddr = (const struct sockaddr_dl *)ptr->ifa_addr;
151 base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
152 memcpy(mac, base, min(dlAddr->sdl_alen, 6));
153 break;
154 }
155 ptr = ptr->ifa_next;
156 }
157 freeifaddrs(addrs);
158 }
159 }
160 #endif
161
162 #if WIN
163 #pragma comment(lib, "IPHLPAPI.lib")
164 void get_mac(u8_t mac[]) {
165 IP_ADAPTER_INFO AdapterInfo[16];
166 DWORD dwBufLen = sizeof(AdapterInfo);
167 DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen);
168
169 mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
170
171 if (GetAdaptersInfo(AdapterInfo, &dwBufLen) == ERROR_SUCCESS) {
172 memcpy(mac, AdapterInfo[0].Address, 6);
173 }
174 }
175 #endif
176
177 void set_nonblock(sockfd s) {
178 #if WIN
179 u_long iMode = 1;
180 ioctlsocket(s, FIONBIO, &iMode);
181 #else
182 int flags = fcntl(s, F_GETFL,0);
183 fcntl(s, F_SETFL, flags | O_NONBLOCK);
184 #endif
185 }
186
187 // connect for socket already set to non blocking with timeout in seconds
188 int connect_timeout(sockfd sock, const struct sockaddr *addr, socklen_t addrlen, int timeout) {
189 fd_set w, e;
190 struct timeval tval;
191
192 if (connect(sock, addr, addrlen) < 0) {
193 #if !WIN
194 if (last_error() != EINPROGRESS) {
195 #else
196 if (last_error() != WSAEWOULDBLOCK) {
197 #endif
198 return -1;
199 }
200 }
201
202 FD_ZERO(&w);
203 FD_SET(sock, &w);
204 e = w;
205 tval.tv_sec = timeout;
206 tval.tv_usec = 0;
207
208 // only return 0 if w set and sock error is zero, otherwise return error code
209 if (select(sock + 1, NULL, &w, &e, timeout ? &tval : NULL) == 1 && FD_ISSET(sock, &w)) {
210 int error = 0;
211 socklen_t len = sizeof(error);
212 getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&error, &len);
213 return error;
214 }
215
216 return -1;
217 }
218
219 void server_addr(char *server, in_addr_t *ip_ptr, unsigned *port_ptr) {
220 struct addrinfo *res = NULL;
221 struct addrinfo hints;
222 const char *port = NULL;
223
224 if (strtok(server, ":")) {
225 port = strtok(NULL, ":");
226 if (port) {
227 *port_ptr = atoi(port);
228 }
229 }
230
231 memset(&hints, 0, sizeof(struct addrinfo));
232 hints.ai_family = AF_INET;
233
234 getaddrinfo(server, NULL, &hints, &res);
235
236 if (res && res->ai_addr) {
237 *ip_ptr = ((struct sockaddr_in*)res->ai_addr)->sin_addr.s_addr;
238 }
239
240 if (res) {
241 freeaddrinfo(res);
242 }
243 }
244
245 void set_readwake_handles(event_handle handles[], sockfd s, event_event e) {
246 #if WINEVENT
247 handles[0] = WSACreateEvent();
248 handles[1] = e;
249 WSAEventSelect(s, handles[0], FD_READ | FD_CLOSE);
250 #elif SELFPIPE
251 handles[0].fd = s;
252 handles[1].fd = e.fds[0];
253 handles[0].events = POLLIN;
254 handles[1].events = POLLIN;
255 #else
256 handles[0].fd = s;
257 handles[1].fd = e;
258 handles[0].events = POLLIN;
259 handles[1].events = POLLIN;
260 #endif
261 }
262
263 event_type wait_readwake(event_handle handles[], int timeout) {
264 #if WINEVENT
265 int wait = WSAWaitForMultipleEvents(2, handles, FALSE, timeout, FALSE);
266 if (wait == WSA_WAIT_EVENT_0) {
267 WSAResetEvent(handles[0]);
268 return EVENT_READ;
269 } else if (wait == WSA_WAIT_EVENT_0 + 1) {
270 return EVENT_WAKE;
271 } else {
272 return EVENT_TIMEOUT;
273 }
274 #else
275 if (poll(handles, 2, timeout) > 0) {
276 if (handles[0].revents) {
277 return EVENT_READ;
278 }
279 if (handles[1].revents) {
280 wake_clear(handles[1].fd);
281 return EVENT_WAKE;
282 }
283 }
284 return EVENT_TIMEOUT;
285 #endif
286 }
287
288 // pack/unpack to network byte order
289 void packN(u32_t *dest, u32_t val) {
290 u8_t *ptr = (u8_t *)dest;
291 *(ptr) = (val >> 24) & 0xFF; *(ptr+1) = (val >> 16) & 0xFF; *(ptr+2) = (val >> 8) & 0xFF; *(ptr+3) = val & 0xFF;
292 }
293
294 void packn(u16_t *dest, u16_t val) {
295 u8_t *ptr = (u8_t *)dest;
296 *(ptr) = (val >> 8) & 0xFF; *(ptr+1) = val & 0xFF;
297 }
298
299 u32_t unpackN(u32_t *src) {
300 u8_t *ptr = (u8_t *)src;
301 return *(ptr) << 24 | *(ptr+1) << 16 | *(ptr+2) << 8 | *(ptr+3);
302 }
303
304 u16_t unpackn(u16_t *src) {
305 u8_t *ptr = (u8_t *)src;
306 return *(ptr) << 8 | *(ptr+1);
307 }
308
309 #if OSX
310 void set_nosigpipe(sockfd s) {
311 int set = 1;
312 setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
313 }
314 #endif
315
316 #if WIN
317 void winsock_init(void) {
318 WSADATA wsaData;
319 WORD wVersionRequested = MAKEWORD(2, 2);
320 int WSerr = WSAStartup(wVersionRequested, &wsaData);
321 if (WSerr != 0) {
322 LOG_ERROR("Bad winsock version");
323 exit(1);
324 }
325 }
326
327 void winsock_close(void) {
328 WSACleanup();
329 }
330
331 void *dlopen(const char *filename, int flag) {
332 SetLastError(0);
333 return LoadLibrary((LPCTSTR)filename);
334 }
335
336 void *dlsym(void *handle, const char *symbol) {
337 SetLastError(0);
338 return (void *)GetProcAddress(handle, symbol);
339 }
340
341 char *dlerror(void) {
342 static char ret[32];
343 int last = GetLastError();
344 if (last) {
345 sprintf(ret, "code: %i", last);
346 SetLastError(0);
347 return ret;
348 }
349 return NULL;
350 }
351
352 // this only implements numfds == 1
353 int poll(struct pollfd *fds, unsigned long numfds, int timeout) {
354 fd_set r, w;
355 struct timeval tv;
356 int ret;
357
358 FD_ZERO(&r);
359 FD_ZERO(&w);
360
361 if (fds[0].events & POLLIN) FD_SET(fds[0].fd, &r);
362 if (fds[0].events & POLLOUT) FD_SET(fds[0].fd, &w);
363
364 tv.tv_sec = timeout / 1000;
365 tv.tv_usec = 1000 * (timeout % 1000);
366
367 ret = select(fds[0].fd + 1, &r, &w, NULL, &tv);
368
369 if (ret < 0) return ret;
370
371 fds[0].revents = 0;
372 if (FD_ISSET(fds[0].fd, &r)) fds[0].revents |= POLLIN;
373 if (FD_ISSET(fds[0].fd, &w)) fds[0].revents |= POLLOUT;
374
375 return ret;
376 }
377
378 #endif
379
380 #if LINUX || FREEBSD
381 void touch_memory(u8_t *buf, size_t size) {
382 u8_t *ptr;
383 for (ptr = buf; ptr < buf + size; ptr += sysconf(_SC_PAGESIZE)) {
384 *ptr = 0;
385 }
386 }
387 #endif
0 /*
1 * Squeezelite - lightweight headless squeezebox emulator
2 *
3 * (c) Adrian Smith 2012-2015, triode1@btinternet.com
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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
20 #include "squeezelite.h"
21
22 // automatically select between floating point (preferred) and fixed point libraries:
23 // NOTE: works with Tremor version here: http://svn.xiph.org/trunk/Tremor, not vorbisidec.1.0.2 currently in ubuntu
24
25 // we take common definations from <vorbis/vorbisfile.h> even though we can use tremor at run time
26 // tremor's OggVorbis_File struct is normally smaller so this is ok, but padding added to malloc in case it is bigger
27 #define OV_EXCLUDE_STATIC_CALLBACKS
28
29 #include <vorbis/vorbisfile.h>
30
31 struct vorbis {
32 OggVorbis_File *vf;
33 bool opened;
34 #if !LINKALL
35 // vorbis symbols to be dynamically loaded - from either vorbisfile or vorbisidec (tremor) version of library
36 vorbis_info *(* ov_info)(OggVorbis_File *vf, int link);
37 int (* ov_clear)(OggVorbis_File *vf);
38 long (* ov_read)(OggVorbis_File *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream);
39 long (* ov_read_tremor)(OggVorbis_File *vf, char *buffer, int length, int *bitstream);
40 int (* ov_open_callbacks)(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
41 #endif
42 };
43
44 static struct vorbis *v;
45
46 extern log_level loglevel;
47
48 extern struct buffer *streambuf;
49 extern struct buffer *outputbuf;
50 extern struct streamstate stream;
51 extern struct outputstate output;
52 extern struct decodestate decode;
53 extern struct processstate process;
54
55 #define LOCK_S mutex_lock(streambuf->mutex)
56 #define UNLOCK_S mutex_unlock(streambuf->mutex)
57 #define LOCK_O mutex_lock(outputbuf->mutex)
58 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
59 #if PROCESS
60 #define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
61 #define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
62 #define LOCK_O_not_direct if (!decode.direct) mutex_lock(outputbuf->mutex)
63 #define UNLOCK_O_not_direct if (!decode.direct) mutex_unlock(outputbuf->mutex)
64 #define IF_DIRECT(x) if (decode.direct) { x }
65 #define IF_PROCESS(x) if (!decode.direct) { x }
66 #else
67 #define LOCK_O_direct mutex_lock(outputbuf->mutex)
68 #define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
69 #define LOCK_O_not_direct
70 #define UNLOCK_O_not_direct
71 #define IF_DIRECT(x) { x }
72 #define IF_PROCESS(x)
73 #endif
74
75 #if LINKALL
76 #define OV(h, fn, ...) (ov_ ## fn)(__VA_ARGS__)
77 #define TREMOR(h) 0
78 extern int ov_read_tremor(); // needed to enable compilation, not linked
79 #else
80 #define OV(h, fn, ...) (h)->ov_##fn(__VA_ARGS__)
81 #define TREMOR(h) (h)->ov_read_tremor
82 #endif
83
84 // called with mutex locked within vorbis_decode to avoid locking O before S
85 static size_t _read_cb(void *ptr, size_t size, size_t nmemb, void *datasource) {
86 size_t bytes;
87
88 bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
89 bytes = min(bytes, size * nmemb);
90
91 memcpy(ptr, streambuf->readp, bytes);
92 _buf_inc_readp(streambuf, bytes);
93
94 return bytes / size;
95 }
96
97 // these are needed for older versions of tremor, later versions and libvorbis allow NULL to be used
98 static int _seek_cb(void *datasource, ogg_int64_t offset, int whence) { return -1; }
99 static int _close_cb(void *datasource) { return 0; }
100 static long _tell_cb(void *datasource) { return 0; }
101
102 static decode_state vorbis_decode(void) {
103 static int channels;
104 bool end;
105 frames_t frames;
106 int bytes, s, n;
107 u8_t *write_buf;
108
109 LOCK_S;
110 LOCK_O_direct;
111 end = (stream.state <= DISCONNECT);
112
113 IF_DIRECT(
114 frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
115 );
116 IF_PROCESS(
117 frames = process.max_in_frames;
118 );
119
120 if (!frames && end) {
121 UNLOCK_O_direct;
122 UNLOCK_S;
123 return DECODE_COMPLETE;
124 }
125
126 if (decode.new_stream) {
127 ov_callbacks cbs;
128 int err;
129 struct vorbis_info *info;
130
131 cbs.read_func = _read_cb;
132
133 if (TREMOR(v)) {
134 cbs.seek_func = _seek_cb; cbs.close_func = _close_cb; cbs.tell_func = _tell_cb;
135 } else {
136 cbs.seek_func = NULL; cbs.close_func = NULL; cbs.tell_func = NULL;
137 }
138
139 if ((err = OV(v, open_callbacks, streambuf, v->vf, NULL, 0, cbs)) < 0) {
140 LOG_WARN("open_callbacks error: %d", err);
141 UNLOCK_O_direct;
142 UNLOCK_S;
143 return DECODE_COMPLETE;
144 }
145 v->opened = true;
146
147 info = OV(v, info, v->vf, -1);
148
149 LOG_INFO("setting track_start");
150 LOCK_O_not_direct;
151 output.next_sample_rate = decode_newstream(info->rate, output.supported_rates);
152 IF_DSD( output.next_dop = false; )
153 output.track_start = outputbuf->writep;
154 if (output.fade_mode) _checkfade(true);
155 decode.new_stream = false;
156 UNLOCK_O_not_direct;
157
158 IF_PROCESS(
159 frames = process.max_in_frames;
160 );
161
162 channels = info->channels;
163
164 if (channels > 2) {
165 LOG_WARN("too many channels: %d", channels);
166 UNLOCK_O_direct;
167 UNLOCK_S;
168 return DECODE_ERROR;
169 }
170 }
171
172 bytes = frames * 2 * channels; // samples returned are 16 bits
173
174 IF_DIRECT(
175 write_buf = outputbuf->writep;
176 );
177 IF_PROCESS(
178 write_buf = process.inbuf;
179 );
180
181 // write the decoded frames into outputbuf even though they are 16 bits per sample, then unpack them
182 if (!TREMOR(v)) {
183 #if SL_LITTLE_ENDIAN
184 n = OV(v, read, v->vf, (char *)write_buf, bytes, 0, 2, 1, &s);
185 #else
186 n = OV(v, read, v->vf, (char *)write_buf, bytes, 1, 2, 1, &s);
187 #endif
188 } else {
189 n = OV(v, read_tremor, v->vf, (char *)write_buf, bytes, &s);
190 }
191
192 if (n > 0) {
193
194 frames_t count;
195 s16_t *iptr;
196 s32_t *optr;
197
198 frames = n / 2 / channels;
199 count = frames * channels;
200
201 // work backward to unpack samples to 4 bytes per sample
202 iptr = (s16_t *)write_buf + count;
203 optr = (s32_t *)write_buf + frames * 2;
204
205 if (channels == 2) {
206 while (count--) {
207 *--optr = *--iptr << 16;
208 }
209 } else if (channels == 1) {
210 while (count--) {
211 *--optr = *--iptr << 16;
212 *--optr = *iptr << 16;
213 }
214 }
215
216 IF_DIRECT(
217 _buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
218 );
219 IF_PROCESS(
220 process.in_frames = frames;
221 );
222
223 LOG_SDEBUG("wrote %u frames", frames);
224
225 } else if (n == 0) {
226
227 LOG_INFO("end of stream");
228 UNLOCK_O_direct;
229 UNLOCK_S;
230 return DECODE_COMPLETE;
231
232 } else if (n == OV_HOLE) {
233
234 // recoverable hole in stream, seen when skipping
235 LOG_DEBUG("hole in stream");
236
237 } else {
238
239 LOG_INFO("ov_read error: %d", n);
240 UNLOCK_O_direct;
241 UNLOCK_S;
242 return DECODE_COMPLETE;
243 }
244
245 UNLOCK_O_direct;
246 UNLOCK_S;
247
248 return DECODE_RUNNING;
249 }
250
251 static void vorbis_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
252 if (!v->vf) {
253 v->vf = malloc(sizeof(OggVorbis_File) + 128); // add some padding as struct size may be larger
254 memset(v->vf, 0, sizeof(OggVorbis_File) + 128);
255 } else {
256 if (v->opened) {
257 OV(v, clear, v->vf);
258 v->opened = false;
259 }
260 }
261 }
262
263 static void vorbis_close(void) {
264 if (v->opened) {
265 OV(v, clear, v->vf);
266 v->opened = false;
267 }
268 free(v->vf);
269 v->vf = NULL;
270 }
271
272 static bool load_vorbis() {
273 #if !LINKALL
274 void *handle = dlopen(LIBVORBIS, RTLD_NOW);
275 char *err;
276 bool tremor = false;
277
278 if (!handle) {
279 handle = dlopen(LIBTREMOR, RTLD_NOW);
280 if (handle) {
281 tremor = true;
282 } else {
283 LOG_INFO("dlerror: %s", dlerror());
284 return false;
285 }
286 }
287
288 v->ov_read = tremor ? NULL : dlsym(handle, "ov_read");
289 v->ov_read_tremor = tremor ? dlsym(handle, "ov_read") : NULL;
290 v->ov_info = dlsym(handle, "ov_info");
291 v->ov_clear = dlsym(handle, "ov_clear");
292 v->ov_open_callbacks = dlsym(handle, "ov_open_callbacks");
293
294 if ((err = dlerror()) != NULL) {
295 LOG_INFO("dlerror: %s", err);
296 return false;
297 }
298
299 LOG_INFO("loaded %s", tremor ? LIBTREMOR : LIBVORBIS);
300 #endif
301
302 return true;
303 }
304
305 struct codec *register_vorbis(void) {
306 static struct codec ret = {
307 'o', // id
308 "ogg", // types
309 2048, // min read
310 20480, // min space
311 vorbis_open, // open
312 vorbis_close, // close
313 vorbis_decode,// decode
314 };
315
316 v = malloc(sizeof(struct vorbis));
317 if (!v) {
318 return NULL;
319 }
320
321 v->vf = NULL;
322 v->opened = false;
323
324 if (!load_vorbis()) {
325 return NULL;
326 }
327
328 LOG_INFO("using vorbis to decode ogg");
329 return &ret;
330 }