diff --git a/Makefile b/Makefile index eac4039..59d7b3b 100644 --- a/Makefile +++ b/Makefile @@ -5,26 +5,28 @@ EXECUTABLE ?= squeezelite # passing one or more of these in $(OPTS) enables optional feature inclusion -OPT_DSD = -DDSD -OPT_FF = -DFFMPEG -OPT_ALAC = -DALAC -OPT_LINKALL = -DLINKALL -OPT_RESAMPLE= -DRESAMPLE -OPT_VIS = -DVISEXPORT -OPT_IR = -DIR -OPT_GPIO = -DGPIO -OPT_RPI = -DRPI -OPT_NO_FAAD = -DNO_FAAD -OPT_SSL = -DUSE_SSL -OPT_NOSSLSYM= -DNO_SSLSYM -OPT_OPUS = -DOPUS -OPT_PORTAUDIO = -DPORTAUDIO +OPT_DSD = -DDSD +OPT_FF = -DFFMPEG +OPT_ALAC = -DALAC +OPT_LINKALL = -DLINKALL +OPT_RESAMPLE = -DRESAMPLE +OPT_VIS = -DVISEXPORT +OPT_IR = -DIR +OPT_GPIO = -DGPIO +OPT_RPI = -DRPI +OPT_NO_FAAD = -DNO_FAAD +OPT_NO_MAD = -DNO_MAD +OPT_NO_MPG123 = -DNO_MPG123 +OPT_SSL = -DUSE_SSL +OPT_NOSSLSYM = -DNO_SSLSYM +OPT_OPUS = -DOPUS +OPT_PORTAUDIO = -DPORTAUDIO OPT_PULSEAUDIO = -DPULSEAUDIO SOURCES = \ main.c slimproto.c buffer.c stream.c utils.c \ output.c output_alsa.c output_pa.c output_stdout.c output_pack.c output_pulse.c decode.c \ - flac.c pcm.c mad.c vorbis.c mpg.c + flac.c pcm.c vorbis.c SOURCES_DSD = dsd.c dop.c dsd2pcm/dsd2pcm.c SOURCES_FF = ffmpeg.c @@ -37,6 +39,8 @@ SOURCES_FAAD = faad.c SOURCES_SSL = sslsym.c SOURCES_OPUS = opus.c +SOURCES_MAD = mad.c +SOURCES_MPG123 = mpg.c LINK_LINUX = -ldl LINK_ALSA = -lasound @@ -45,12 +49,14 @@ LINK_SSL = -lssl -lcrypto LINK_ALAC = -lalac -LINKALL = -lmad -lmpg123 -lFLAC -lvorbisfile -lvorbis -logg +LINKALL = -lFLAC -lvorbisfile -lvorbis -logg LINKALL_FF = -lavformat -lavcodec -lavutil LINKALL_RESAMPLE = -lsoxr LINKALL_IR = -llirc_client LINKALL_FAAD = -lfaad LINKALL_OPUS = -lopusfile -lopus +LINKALL_MAD = -lmad +LINKALL_MPG123 = -lmpg123 DEPS = squeezelite.h slimproto.h @@ -98,6 +104,12 @@ ifneq (,$(findstring $(OPT_SSL), $(OPTS))) SOURCES += $(SOURCES_SSL) endif +ifeq (,$(findstring $(OPT_NO_MAD), $(OPTS))) + SOURCES += $(SOURCES_MAD) +endif +ifeq (,$(findstring $(OPT_NO_MPG123), $(OPTS))) + SOURCES += $(SOURCES_MPG123) +endif # add optional link options ifneq (,$(findstring $(OPT_LINKALL), $(OPTS))) @@ -119,6 +131,12 @@ endif ifneq (,$(findstring $(OPT_SSL), $(OPTS))) LDADD += $(LINK_SSL) +endif +ifeq (,$(findstring $(OPT_NO_MAD), $(OPTS))) + LDADD += $(LINKALL_MAD) +endif +ifeq (,$(findstring $(OPT_NO_MPG123), $(OPTS))) + LDADD += $(LINKALL_MPG123) endif else # if not LINKALL and linux add LINK_LINUX diff --git a/Makefile.i386 b/Makefile.i386 index 6e58824..c2ff131 100644 --- a/Makefile.i386 +++ b/Makefile.i386 @@ -1,7 +1,7 @@ -# OSX 10.5 Intel 32-bit -OPTS = -DPORTAUDIO -DALAC -DOPUS -DRESAMPLE -DGPIO -DLINKALL -DVISEXPORT -DDSD -DUSE_SSL -I./include -I./include/opus -I./include/alac -O2 -I./include -isysroot /Developer/SDKs/MacOSX10.5.sdk -arch i386 +# OSX 10.7 Intel 32-bit +OPTS = -DPORTAUDIO -DALAC -DOPUS -DRESAMPLE -DLINKALL -DVISEXPORT -DDSD -DUSE_SSL -I./include -I./include/opus -I./include/alac -I./include -O3 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -arch i386 -mmacosx-version-min=10.7 -LDFLAGS = -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk -arch i386 -mmacosx-version-min=10.5 -L./lib +LDFLAGS = -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -arch i386 -mmacosx-version-min=10.7 -L./lib LDADD = -lportaudio -lpthread -ldl -lm -framework CoreVideo -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon diff --git a/Makefile.m1 b/Makefile.m1 new file mode 100644 index 0000000..4ca5fd5 --- /dev/null +++ b/Makefile.m1 @@ -0,0 +1,8 @@ +# OSX 11.0+ arm64 only +OPTS = -DPORTAUDIO -DALAC -DOPUS -DRESAMPLE -DLINKALL -DVISEXPORT -DDSD -DUSE_SSL -I./includem1 -I./includem1/opus -I./includem1/alac -arch arm64 -O3 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -mmacosx-version-min=11.0 + +LDFLAGS = -arch arm64 -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -mmacosx-version-min=11.0 -L./libm1 + +LDADD = -lportaudio -lpthread -ldl -lm -framework CoreVideo -framework VideoDecodeAcceleration -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon + +include Makefile diff --git a/Makefile.x86_64 b/Makefile.x86_64 index 0289a11..18e4d2b 100644 --- a/Makefile.x86_64 +++ b/Makefile.x86_64 @@ -1,5 +1,5 @@ # OSX 10.7+ 64-bit only -OPTS = -DPORTAUDIO -DALAC -DOPUS -DRESAMPLE -DGPIO -DLINKALL -DVISEXPORT -DDSD -DUSE_SSL -I./include64 -I./include64/opus -I./include64/alac -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -arch x86_64 -mmacosx-version-min=10.7 +OPTS = -DPORTAUDIO -DALAC -DOPUS -DRESAMPLE -DLINKALL -DVISEXPORT -DDSD -DUSE_SSL -I./include64 -I./include64/opus -I./include64/alac -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -arch x86_64 -mmacosx-version-min=10.7 LDFLAGS = -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -arch x86_64 -mmacosx-version-min=10.7 -L./lib64 diff --git a/alac.c b/alac.c index b8b524b..6de2640 100644 --- a/alac.c +++ b/alac.c @@ -120,8 +120,15 @@ // extract audio config from within alac if (!strcmp(type, "alac") && bytes > len) { u8_t *ptr = streambuf->readp + 36; - l->decoder = alac_create_decoder(len - 36, ptr, &l->sample_size, &l->sample_rate, &l->channels); - l->play = l->trak; + unsigned int block_size; + l->play = l->trak; + l->decoder = alac_create_decoder(len - 36, ptr, &l->sample_size, &l->sample_rate, &l->channels, &block_size); + l->writebuf = malloc(block_size + 256); + LOG_INFO("allocated write buffer of %u bytes", block_size); + if (!l->writebuf) { + LOG_ERROR("allocation failed"); + return -1; + } } // extract the total number of samples from stts @@ -376,10 +383,9 @@ // need to create a buffer with contiguous data if (bytes < block_size) { - u8_t *buffer = malloc(block_size); - memcpy(buffer, streambuf->readp, bytes); - memcpy(buffer + bytes, streambuf->buf, block_size - bytes); - iptr = buffer; + iptr = malloc(block_size); + memcpy(iptr, streambuf->readp, bytes); + memcpy(iptr + bytes, streambuf->buf, block_size - bytes); } else iptr = streambuf->readp; if (!alac_to_pcm(l->decoder, iptr, l->writebuf, 2, &frames)) { @@ -474,6 +480,7 @@ } } else if (l->sample_size == 16) { u16_t *_iptr = (u16_t*) iptr; + iptr += count * 4; while (count--) { *optr++ = ALIGN16(*_iptr++); *optr++ = ALIGN16(*_iptr++); @@ -486,6 +493,7 @@ } } else if (l->sample_size == 32) { u32_t *_iptr = (u32_t*) iptr; + iptr += count * 8; while (count--) { *optr++ = ALIGN32(*_iptr++); *optr++ = ALIGN32(*_iptr++); @@ -511,27 +519,17 @@ return DECODE_RUNNING; } -static void alac_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) { - if (l->decoder) alac_delete_decoder(l->decoder); - else l->writebuf = malloc(BLOCK_SIZE * 2); - +static void alac_close(void) { + if (l->decoder) alac_delete_decoder(l->decoder); + if (l->writebuf) free(l->writebuf); if (l->chunkinfo) free(l->chunkinfo); if (l->block_size) free(l->block_size); if (l->stsc) free(l->stsc); - l->decoder = l->chunkinfo = l->stsc = l->block_size = NULL; - l->skip = 0; - l->samples = l->sttssamples = 0; - l->empty = false; - l->pos = l->consume = l->sample = l->nextchunk = 0; + memset(l, 0, sizeof(struct alac)); } -static void alac_close(void) { - if (l->decoder) alac_delete_decoder(l->decoder); - if (l->chunkinfo) free(l->chunkinfo); - if (l->block_size) free(l->block_size); - if (l->stsc) free(l->stsc); - l->decoder = l->chunkinfo = l->stsc = l->block_size = NULL; - free(l->writebuf); +static void alac_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) { + alac_close(); } struct codec *register_alac(void) { @@ -544,14 +542,10 @@ alac_close, // close alac_decode, // decode }; - - l = malloc(sizeof(struct alac)); - if (!l) { - return NULL; - } - - l->decoder = l->chunkinfo = l->stsc = l->block_size = NULL; - + + l = calloc(1, sizeof(struct alac)); + if (!l) return NULL; + LOG_INFO("using alac to decode alc"); return &ret; } diff --git a/alac_wrapper.cpp b/alac_wrapper.cpp index 427b9b4..35c6842 100644 --- a/alac_wrapper.cpp +++ b/alac_wrapper.cpp @@ -32,7 +32,7 @@ /*----------------------------------------------------------------------------*/ extern "C" struct alac_codec_s *alac_create_decoder(int magic_cookie_size, unsigned char *magic_cookie, unsigned char *sample_size, unsigned *sample_rate, - unsigned char *channels) { + unsigned char *channels, unsigned int *block_size) { struct alac_codec_s *codec = (struct alac_codec_s*) malloc(sizeof(struct alac_codec_s)); codec->Decoder = new ALACDecoder; @@ -43,7 +43,7 @@ *sample_size = codec->Decoder->mConfig.bitDepth; codec->frames_per_packet = codec->Decoder->mConfig.frameLength; - codec->block_size = codec->frames_per_packet * (*channels) * (*sample_size) / 8; + *block_size = codec->block_size = codec->frames_per_packet * (*channels) * (*sample_size) / 8; return codec; } diff --git a/alac_wrapper.h b/alac_wrapper.h index 5f01483..d37692f 100644 --- a/alac_wrapper.h +++ b/alac_wrapper.h @@ -28,7 +28,7 @@ struct alac_codec_s *alac_create_decoder(int magic_cookie_size, unsigned char *magic_cookie, unsigned char *sample_size, unsigned *sample_rate, - unsigned char *channels); + unsigned char *channels, unsigned int *block_size); void alac_delete_decoder(struct alac_codec_s *codec); bool alac_to_pcm(struct alac_codec_s *codec, unsigned char* input, unsigned char *output, char channels, unsigned *out_frames); diff --git a/alpine/APKBUILD b/alpine/APKBUILD index 6f5267a..cf0581a 100644 --- a/alpine/APKBUILD +++ b/alpine/APKBUILD @@ -1,15 +1,15 @@ # Contributor: Carl Chave # Maintainer: Ralph Irving pkgname=squeezelite -pkgver=1.9.7.1273 -pkgrel=1 +pkgver=1.9.9.1401 +pkgrel=0 pkgdesc="Lightweight headless squeezebox player for Logitech Media Server" url="https://github.com/ralph-irving/squeezelite" arch="all" license="GPL-3.0-or-later3" options="!check" # No test suite -depends="flac alsa-lib faad2 mpg123 libvorbis libmad soxr openssl opusfile libalac" -makedepends="flac-dev alsa-lib-dev faad2-dev mpg123-dev libvorbis-dev libmad-dev soxr-dev openssl-dev opusfile-dev opus-dev libalac-dev" +depends="flac alsa-lib faad2-libs mpg123-libs libvorbis libmad soxr openssl opusfile libalac lirc" +makedepends="flac-dev alsa-lib-dev faad2-dev mpg123-dev libvorbis-dev libmad-dev soxr-dev openssl-dev opusfile-dev opus-dev libalac-dev lirc-dev" install="$pkgname.pre-install" subpackages="$pkgname-doc $pkgname-openrc" source="$pkgname-$pkgver.zip::https://github.com/ralph-irving/squeezelite/archive/master.zip load-libtremor-first.patch $pkgname.confd $pkgname.initd" @@ -17,7 +17,7 @@ build() { cd "$builddir" - make OPTS="-DRESAMPLE -DDSD -DGPIO -DVISEXPORT -DUSE_SSL -DNO_SSLSYM -DOPUS -DALAC -I/usr/include/opus -I/usr/include/alac" + make OPTS="-DRESAMPLE -DDSD -DGPIO -DVISEXPORT -DUSE_SSL -DNO_SSLSYM -DOPUS -DALAC -DIR -I/usr/include/opus -I/usr/include/alac" gcc -Os -fomit-frame-pointer -fcommon -s -o find_servers tools/find_servers.c gcc -Os -fomit-frame-pointer -fcommon -s -o alsacap tools/alsacap.c -lasound } diff --git a/alpine/libalac/APKBUILD b/alpine/libalac/APKBUILD index 0328877..b165ce0 100644 --- a/alpine/libalac/APKBUILD +++ b/alpine/libalac/APKBUILD @@ -7,7 +7,7 @@ arch="all" subpackages="$pkgname-doc $pkgname-dev" license="Apache 2.0" -makedepends="git autoconf automake make tar" +makedepends="git autoconf automake libtool make tar" source="fix-arm-segfault.patch \ alac-version.patch" @@ -45,5 +45,5 @@ install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/COPYING } -sha512sums="e72b13714476170108844b84c0043dc06d2ff2e8c9b651a7ad1571d148fc5567aca48048646d16fb82630d6972a31b9328f04e522972b297d1cf8e804785867f fix-arm-segfault.patch +sha512sums="271d4c5184c7f48ac79c8f8f9f3bc39f7f970b4d98acda792e40450b687f211094b4dcaea23e034d4deb7ea78713b95e691db9c09fbf31b1be59b6d525ef11a8 fix-arm-segfault.patch 093379f79b5dc9f5b8aa45826d61738b088d78305a7d514df33851ae34d02ee9034a8ecddf2558fcb1bf4daaf64c620ea4411521908cfc748e31fd0a2d50bbf7 alac-version.patch" diff --git a/alpine/squeezelite.initd b/alpine/squeezelite.initd index ba6aa26..6fffea7 100644 --- a/alpine/squeezelite.initd +++ b/alpine/squeezelite.initd @@ -4,7 +4,7 @@ depend() { need net - use alsasound + use alsa after bootmisc } diff --git a/buffer.c b/buffer.c index 125661f..0fd2b05 100644 --- a/buffer.c +++ b/buffer.c @@ -27,7 +27,10 @@ // _* called with muxtex locked -inline unsigned _buf_used(struct buffer *buf) { +#if !WIN +inline +#endif +unsigned _buf_used(struct buffer *buf) { return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->size - (buf->readp - buf->writep); } diff --git a/debian/changelog b/debian/changelog index 7c636db..5bc00b7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +squeezelite (1.9+git20221015.ca44fc6-1) UNRELEASED; urgency=low + + * New upstream snapshot. + + -- Debian Janitor Tue, 18 Oct 2022 03:41:15 -0000 + squeezelite (1.9+git20210102.78fef68-3) unstable; urgency=medium * Upload to unstable. diff --git a/decode.c b/decode.c index 16949ea..04af5d5 100644 --- a/decode.c +++ b/decode.c @@ -183,6 +183,7 @@ if (!strstr(exclude_codecs, "pcm") && (!include_codecs || (order_codecs = strstr(include_codecs, "pcm")))) sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_pcm()); +#if !defined(NO_MAD) && !defined(NO_MPG123) // try mad then mpg for mp3 unless command line option passed if (!(strstr(exclude_codecs, "mp3") || strstr(exclude_codecs, "mad")) && (!include_codecs || (order_codecs = strstr(include_codecs, "mp3")) || (order_codecs = strstr(include_codecs, "mad")))) @@ -190,6 +191,13 @@ else if (!(strstr(exclude_codecs, "mp3") || strstr(exclude_codecs, "mpg")) && (!include_codecs || (order_codecs = strstr(include_codecs, "mp3")) || (order_codecs = strstr(include_codecs, "mpg")))) sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_mpg()); +#elif !defined(NO_MAD) + if (!strstr(exclude_codecs, "mp3") && (!include_codecs || (order_codecs = strstr(include_codecs, "mp3")))) + sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_mad()); +#elif !defined(NO_MPG123) + if (!strstr(exclude_codecs, "mp3") && (!include_codecs || (order_codecs = strstr(include_codecs, "mp3")))) + sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_mpg()); +#endif LOG_DEBUG("include codecs: %s exclude codecs: %s", include_codecs ? include_codecs : "", exclude_codecs); diff --git a/ffmpeg.c b/ffmpeg.c index c16805d..229a40b 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -54,14 +54,10 @@ unsigned (* avcodec_version)(void); AVCodec * (* avcodec_find_decoder)(int); int attribute_align_arg (* avcodec_open2)(AVCodecContext *, const AVCodec *, AVDictionary **); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) AVFrame * (* av_frame_alloc)(void); void (* av_frame_free)(AVFrame **); -#else - AVFrame * (* avcodec_alloc_frame)(void); - void (* avcodec_free_frame)(AVFrame **); -#endif - int attribute_align_arg (* avcodec_decode_audio4)(AVCodecContext *, AVFrame *, int *, const AVPacket *); + int attribute_align_arg (* avcodec_send_packet)(AVCodecContext *, const AVPacket *); + int attribute_align_arg (* avcodec_receive_frame)(AVCodecContext *, AVFrame *); AVCodecContext * (* avcodec_alloc_context3)(const AVCodec *); void (* avcodec_free_context)(AVCodecContext **); int (* avcodec_parameters_to_context)(AVCodecContext *, const AVCodecParameters *); @@ -73,15 +69,16 @@ int (* avformat_find_stream_info)(AVFormatContext *, AVDictionary **); AVIOContext * (* avio_alloc_context)(unsigned char *, int, int, void *, int (*read_packet)(void *, uint8_t *, int), int (*write_packet)(void *, uint8_t *, int), int64_t (*seek)(void *, int64_t, int)); + AVPacket * (* av_packet_alloc)(void); +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,133,100) void (* av_init_packet)(AVPacket *); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,24,102) +#endif void (* av_packet_unref)(AVPacket *); -#else - void (* av_free_packet)(AVPacket *); -#endif int (* av_read_frame)(AVFormatContext *, AVPacket *); AVInputFormat * (* av_find_input_format)(const char *); +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100) void (* av_register_all)(void); +#endif // ffmpeg symbols to be dynamically loaded from libavutil unsigned (* avutil_version)(void); void (* av_log_set_callback)(void (*)(void*, int, const char*, va_list)); @@ -263,8 +260,7 @@ } static decode_state ff_decode(void) { - int r, len, got_frame; - AVPacket pkt_c; + int r; s32_t *optr = NULL; if (decode.new_stream) { @@ -351,21 +347,16 @@ AVCODEC(ff, open2, ff->codecC, codec, NULL); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) ff->frame = AV(ff, frame_alloc); -#else - ff->frame = AVCODEC(ff, alloc_frame); -#endif - - ff->avpkt = AV(ff, malloc, sizeof(AVPacket)); + ff->avpkt = AV(ff, packet_alloc); if (ff->avpkt == NULL) { LOG_ERROR("can't allocate avpkt"); return DECODE_ERROR; } - AV(ff, init_packet, ff->avpkt); - ff->avpkt->data = NULL; - ff->avpkt->size = 0; +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,133,100) + AV(ff, init_packet, ff->avpkt); // on older ffmpeg, this still is needed to e.g. set ->pos to -1 +#endif LOCK_O; LOG_INFO("setting track_start"); @@ -376,8 +367,6 @@ decode.new_stream = false; UNLOCK_O; } - - got_frame = 0; if ((r = AV(ff, read_frame, ff->formatC, ff->avpkt)) < 0) { if (r == AVERROR_EOF) { @@ -393,27 +382,30 @@ return DECODE_RUNNING; } - // clone packet as we are adjusting it - pkt_c = *ff->avpkt; - IF_PROCESS( optr = (s32_t *)process.inbuf; process.in_frames = 0; ); - while (pkt_c.size > 0 || got_frame) { - - len = AVCODEC(ff, decode_audio4, ff->codecC, ff->frame, &got_frame, &pkt_c); - if (len < 0) { - LOG_ERROR("avcodec_decode_audio4 error: %i %s", len, av__err2str(len)); - break; // exit loop, free the packet, and continue decoding - } - - pkt_c.data += len; - pkt_c.size -= len; - - if (got_frame) { - + if ((r = AVCODEC(ff, send_packet, ff->codecC, ff->avpkt)) < 0) { + AV(ff, packet_unref, ff->avpkt); + + if (r == AVERROR_EOF) { + LOG_DEBUG("av_send_packet reports eof"); + return DECODE_COMPLETE; + } else { + LOG_ERROR("av_send_packet error: %i %s", r, av__err2str(r)); + + // EAGAIN is treated as an unrecoverable error here since all pending output frames are processed below + if (r == AVERROR(EAGAIN) || r == AVERROR(EINVAL) || r == AVERROR(ENOMEM)) + return DECODE_ERROR; + + // retain existing behavior (continue decoding) for legitimate decoding errors + return DECODE_RUNNING; + } + } else { + // a single input packet can lead to multiple output frames - process all of them + while ((r = AVCODEC(ff, receive_frame, ff->codecC, ff->frame)) >= 0) { s16_t *iptr16 = (s16_t *)ff->frame->data[0]; s32_t *iptr32 = (s32_t *)ff->frame->data[0]; s16_t *iptr16l = (s16_t *)ff->frame->data[0]; @@ -536,11 +528,21 @@ } } -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,24,102) AV(ff, packet_unref, ff->avpkt); -#else - AV(ff, free_packet, ff->avpkt); -#endif + + if (r == AVERROR(EAGAIN)) { + // EAGAIN is expected if there are no more pending frames + } else if (r == AVERROR_EOF) { + LOG_DEBUG("av_receive_frame reports eof"); + return DECODE_COMPLETE; + } else { + LOG_ERROR("av_receive_frame error: %i %s", r, av__err2str(r)); + + if (r == AVERROR(EINVAL)) + return DECODE_ERROR; + + // retain existing behavior (continue decoding) for legitimate decoding errors + } return DECODE_RUNNING; } @@ -565,31 +567,12 @@ } if (ff->frame) { - // ffmpeg version dependant free function -#if !LINKALL - #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) - ff->av_frame_free ? AV(ff, frame_free, &ff->frame) : AV(ff, freep, &ff->frame); - #else - ff->avcodec_free_frame ? AVCODEC(ff, free_frame, &ff->frame) : AV(ff, freep, &ff->frame); - #endif -#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54,28,0) - #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) AV(ff, frame_free, &ff->frame); - #else - AVCODEC(ff, free_frame, &ff->frame); - #endif -#else - AV(ff, freep, &ff->frame); -#endif ff->frame = NULL; } if (ff->avpkt) { -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,24,102) AV(ff, packet_unref, ff->avpkt); -#else - AV(ff, free_packet, ff->avpkt); -#endif AV(ff, freep, &ff->avpkt); ff->avpkt = NULL; } @@ -661,23 +644,18 @@ ff->avcodec_version = dlsym(handle_codec, "avcodec_version"); ff->avcodec_find_decoder = dlsym(handle_codec, "avcodec_find_decoder"); ff->avcodec_open2 = dlsym(handle_codec, "avcodec_open2"); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) ff->av_frame_alloc = dlsym(handle_codec, "av_frame_alloc"); ff->av_frame_free = dlsym(handle_codec, "av_frame_free"); -#else - ff->avcodec_alloc_frame = dlsym(handle_codec, "avcodec_alloc_frame"); - ff->avcodec_free_frame = dlsym(handle_codec, "avcodec_free_frame"); -#endif - ff->avcodec_decode_audio4 = dlsym(handle_codec, "avcodec_decode_audio4"); + ff->avcodec_send_packet = dlsym(handle_codec, "avcodec_send_packet"); + ff->avcodec_receive_frame = dlsym(handle_codec, "avcodec_receive_frame"); ff->avcodec_alloc_context3 = dlsym(handle_format, "avcodec_alloc_context3"); ff->avcodec_free_context = dlsym(handle_format, "avcodec_free_context"); ff->avcodec_parameters_to_context = dlsym(handle_format, "avcodec_parameters_to_context"); + ff->av_packet_alloc = dlsym(handle_codec, "av_packet_alloc"); +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,133,100) ff->av_init_packet = dlsym(handle_codec, "av_init_packet"); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,24,102) +#endif ff->av_packet_unref = dlsym(handle_codec, "av_packet_unref"); -#else - ff->av_free_packet = dlsym(handle_codec, "av_free_packet"); -#endif if ((err = dlerror()) != NULL) { LOG_INFO("dlerror: %s", err); @@ -694,7 +672,9 @@ ff->avio_alloc_context = dlsym(handle_format, "avio_alloc_context"); ff->av_read_frame = dlsym(handle_format, "av_read_frame"); ff->av_find_input_format= dlsym(handle_format, "av_find_input_format"); +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100) ff->av_register_all = dlsym(handle_format, "av_register_all"); +#endif if ((err = dlerror()) != NULL) { LOG_INFO("dlerror: %s", err); @@ -761,8 +741,10 @@ AV(ff, log_set_callback, av_err_callback); +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100) AV(ff, register_all); - +#endif + registered = true; } @@ -770,7 +752,7 @@ static struct codec ret = { 'w', // id - "wma,wmap", // types + "wma,wmap,wmal", // types READ_SIZE, // min read WRITE_SIZE, // min space ff_open_wma, // open @@ -778,7 +760,7 @@ ff_decode, // decode }; - LOG_INFO("using ffmpeg to decode wma,wmap"); + LOG_INFO("using ffmpeg to decode wma,wmap,wmal"); return &ret; } diff --git a/flac.c b/flac.c index 8475c04..65ea4c8 100644 --- a/flac.c +++ b/flac.c @@ -123,6 +123,10 @@ *want = bytes; + // if there's nothing in the stream buffer, libFLAC will continuously call this function as quickly as possible. slow it down. + if (!bytes && !end) + usleep(1000); + return end ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } diff --git a/ir.c b/ir.c index a2aedd1..922ea64 100644 --- a/ir.c +++ b/ir.c @@ -133,6 +133,7 @@ { "KEY_DOWN", 0x7689b04f, true }, { "KEY_HOME", 0x768922dd, false }, { "KEY_MEDIA_REPEAT", 0x768938c7, false }, + { "KEY_AGAIN", 0x768938c7, false }, // { "KEY_TITLE", 0x76897887, false }, // Now Playing // { "KEY_TITLE", 0x7689a25d, false }, // Now Playing // { "KEY_TEXT", 0x7689f807, false }, // Size diff --git a/main.c b/main.c index 2b736db..df9cb96 100644 --- a/main.c +++ b/main.c @@ -28,7 +28,7 @@ #define TITLE "Squeezelite " VERSION ", Copyright 2012-2015 Adrian Smith, 2015-2021 Ralph Irving." -#define CODECS_BASE "flac,pcm,mp3,ogg" +#define CODECS_BASE "flac,pcm,ogg" #if NO_FAAD #define CODECS_AAC "" #else @@ -51,7 +51,13 @@ #else #define CODECS_DSD "" #endif -#define CODECS_MP3 " (mad,mpg for specific mp3 codec)" +#if !defined(NO_MAD) && !defined(NO_MPG123) +#define CODECS_MP3 ",mp3 (mad,mpg for specific mp3 codec)" +#elif defined(NO_MAD) && defined(NO_MPG123) +#define CODECS_MP3 "" +#else +#define CODECS_MP3 ",mp3" +#endif #define CODECS CODECS_BASE CODECS_AAC CODECS_FF CODECS_OPUS CODECS_DSD CODECS_MP3 @@ -139,9 +145,7 @@ #if LINUX || FREEBSD || SUN " -z \t\t\tDaemonize\n" #endif -#if RESAMPLE " -Z \t\tReport rate to server in helo as the maximum sample rate we can support\n" -#endif " -t \t\t\tLicense terms\n" " -? \t\t\tDisplay this help text\n" "\n" @@ -222,6 +226,12 @@ #endif #if NO_SSLSYM " NO_SSLSYM" +#endif +#if NO_MPG123 + " NO_MPG123" +#endif +#if NO_MAD + " NO_MAD" #endif #if LINKALL " LINKALL" @@ -350,16 +360,9 @@ while (optind < argc && strlen(argv[optind]) >= 2 && argv[optind][0] == '-') { char *opt = argv[optind] + 1; - if (strstr("oabcCdefmMnNpPrs" + if (strstr("oabcCdefmMnNpPrsZ" #if ALSA "UVO" -#endif -/* - * only allow '-Z ' override of maxSampleRate - * reported by client if built with the capability to resample! - */ -#if RESAMPLE - "Z" #endif , opt) && optind < argc - 1) { optarg = argv[optind + 1]; @@ -526,6 +529,9 @@ case 'N': namefile = optarg; break; + case 'Z': + maxSampleRate = atoi(optarg); + break; case 'W': pcm_check_header = true; break; @@ -556,9 +562,6 @@ } else { resample = ""; } - break; - case 'Z': - maxSampleRate = atoi(optarg); break; #endif #if DSD diff --git a/opus.c b/opus.c index 1e1792c..1b80006 100644 --- a/opus.c +++ b/opus.c @@ -189,7 +189,12 @@ // work backward to unpack samples (if needed) iptr = (s16_t *) write_buf + count; - optr = (ISAMPLE_T *) write_buf + frames * 2; + IF_DIRECT( + optr = (ISAMPLE_T *) outputbuf->writep + frames * 2; + ) + IF_PROCESS( + optr = (ISAMPLE_T *) write_buf + frames * 2; + ) if (channels == 2) { #if BYTES_PER_FRAME == 4 @@ -225,7 +230,6 @@ if (stream.state <= DISCONNECT) { LOG_INFO("partial decode"); UNLOCK_O_direct; - UNLOCK_S; return DECODE_COMPLETE; } else { LOG_INFO("no frame decoded"); diff --git a/output.c b/output.c index 7d3fce1..a5044fe 100644 --- a/output.c +++ b/output.c @@ -47,6 +47,7 @@ frames_t frames, size; bool silence; + u8_t flags = output.channels; s32_t cross_gain_in = 0, cross_gain_out = 0; s32_t *cross_ptr = NULL; @@ -59,7 +60,7 @@ silence = false; // start when threshold met - if (output.state == OUTPUT_BUFFER && frames > output.threshold * output.next_sample_rate / 10 && frames > output.start_frames) { + if (output.state == OUTPUT_BUFFER && (frames * BYTES_PER_FRAME) > output.threshold * output.next_sample_rate / 10 && frames > output.start_frames) { output.state = OUTPUT_RUNNING; LOG_INFO("start buffer frames: %u", frames); wake_controller(); @@ -256,8 +257,14 @@ } out_frames = !silence ? min(size, cont_frames) : size; - - wrote = output.write_cb(out_frames, silence, gainL, gainR, cross_gain_in, cross_gain_out, &cross_ptr); + + IF_DSD( + if (output.outfmt != PCM) { + flags = 0; + } + ) + + wrote = output.write_cb(out_frames, silence, gainL, gainR, flags, cross_gain_in, cross_gain_out, &cross_ptr); if (wrote <= 0) { frames -= size; @@ -384,7 +391,7 @@ output.idle_to = (u32_t) idle; /* Skip test_open for stdout, set default sample rates */ - if ( output.device[0] == '-' ) { + if ( output.device[0] == '-' || user_rates ) { for (i = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) { output.supported_rates[i] = rates[i]; } @@ -393,12 +400,6 @@ if (!test_open(output.device, output.supported_rates, user_rates)) { LOG_ERROR("unable to open output device: %s", output.device); exit(0); - } - } - - if (user_rates) { - for (i = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) { - output.supported_rates[i] = rates[i]; } } diff --git a/output_alsa.c b/output_alsa.c index aa663cd..edbbf42 100644 --- a/output_alsa.c +++ b/output_alsa.c @@ -297,6 +297,9 @@ if (snd_pcm_hw_params_test_rate(pcm, hw_params, ref[i], 0) == 0) { rates[ind++] = ref[i]; } + else { + LOG_DEBUG("sample rate %u not supported", ref[i]); + } } } @@ -547,7 +550,7 @@ return 0; } -static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, +static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) { const snd_pcm_channel_area_t *areas; @@ -594,17 +597,14 @@ outputptr = alsa.mmap ? (areas[0].addr + (areas[0].first + offset * areas[0].step) / 8) : alsa.write_buf; - _scale_and_pack_frames(outputptr, inputptr, out_frames, gainL, gainR, output.format); + _scale_and_pack_frames(outputptr, inputptr, out_frames, gainL, gainR, flags, output.format); } else { outputptr = (void *)inputptr; if (!silence) { - - if (gainL != FIXED_ONE || gainR!= FIXED_ONE) { - _apply_gain(outputbuf, out_frames, gainL, gainR); - } + _apply_gain(outputbuf, out_frames, gainL, gainR, flags); } } @@ -676,11 +676,9 @@ #if GPIO // Wake up amp if (gpio_active) { - ampstate = 1; relay(1); } if (power_script != NULL) { - ampstate = 1; relay_script(1); } #endif @@ -810,11 +808,9 @@ #if GPIO // Put Amp to Sleep if (gpio_active){ - ampstate = 0; relay(0); } if (power_script != NULL ){ - ampstate = 0; relay_script(0); } #endif diff --git a/output_pa.c b/output_pa.c index 8729f81..facbba0 100644 --- a/output_pa.c +++ b/output_pa.c @@ -214,6 +214,7 @@ #endif switch (err) { case paInvalidSampleRate: + LOG_DEBUG("sample rate %u not supported", ref[i]); continue; #if WIN #ifndef PA18API @@ -448,7 +449,7 @@ static u8_t *optr; -static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, +static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) { if (!silence) { @@ -458,7 +459,7 @@ } if (gainL != FIXED_ONE || gainR!= FIXED_ONE) { - _apply_gain(outputbuf, out_frames, gainL, gainR); + _apply_gain(outputbuf, out_frames, gainL, gainR, flags); } IF_DSD( diff --git a/output_pack.c b/output_pack.c index 7043f6f..fa855ed 100644 --- a/output_pack.c +++ b/output_pack.c @@ -43,7 +43,32 @@ return (s32_t)(f * 65536.0F); } -void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, output_format format) { +void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, u8_t flags, output_format format) { + // in-place copy input samples if mono/combined is used (never happens with DSD active) + if ((flags & MONO_LEFT) && (flags & MONO_RIGHT)) { + s32_t *ptr = inputptr; + frames_t count = cnt; + while (count--) { + // use 64 bits integer for purists but should really not care + *ptr = *(ptr + 1) = ((s64_t) *ptr + (s64_t) *(ptr + 1)) / 2; + ptr += 2; + } + } else if (flags & MONO_RIGHT) { + s32_t *ptr = inputptr + 1; + frames_t count = cnt; + while (count--) { + *(ptr - 1) = *ptr; + ptr += 2; + } + } else if (flags & MONO_LEFT) { + s32_t *ptr = inputptr; + frames_t count = cnt; + while (count--) { + *(ptr + 1) = *ptr; + ptr += 2; + } + } + switch(format) { #if DSD case U32_LE: @@ -353,13 +378,36 @@ #if !WIN inline #endif -void _apply_gain(struct buffer *outputbuf, frames_t count, s32_t gainL, s32_t gainR) { - s32_t *ptrL = (s32_t *)(void *)outputbuf->readp; - s32_t *ptrR = (s32_t *)(void *)outputbuf->readp + 1; - while (count--) { - *ptrL = gain(gainL, *ptrL); - *ptrR = gain(gainR, *ptrR); - ptrL += 2; - ptrR += 2; +void _apply_gain(struct buffer *outputbuf, frames_t count, s32_t gainL, s32_t gainR, u8_t flags) { + if (gainL == FIXED_ONE && gainR == FIXED_ONE && !(flags & (MONO_LEFT | MONO_RIGHT))) { + return; + } else if ((flags & MONO_LEFT) && (flags & MONO_RIGHT)) { + ISAMPLE_T *ptrL = (ISAMPLE_T *)(void *)outputbuf->readp; + ISAMPLE_T *ptrR = (ISAMPLE_T *)(void *)outputbuf->readp + 1; + while (count--) { + *ptrL = *ptrR = (gain(gainL, *ptrL) + gain(gainR, *ptrR)) / 2; + ptrL += 2; ptrR += 2; + } + + } else if (flags & MONO_RIGHT) { + ISAMPLE_T *ptr = (ISAMPLE_T *)(void *)outputbuf->readp + 1; + while (count--) { + *(ptr - 1) = *ptr = gain(gainR, *ptr); + ptr += 2; + } + } else if (flags & MONO_LEFT) { + ISAMPLE_T *ptr = (ISAMPLE_T *)(void *)outputbuf->readp; + while (count--) { + *(ptr + 1) = *ptr = gain(gainL, *ptr); + ptr += 2; + } + } else { + ISAMPLE_T *ptrL = (ISAMPLE_T *)(void *)outputbuf->readp; + ISAMPLE_T *ptrR = (ISAMPLE_T *)(void *)outputbuf->readp + 1; + while (count--) { + *ptrL = gain(gainL, *ptrL); + *ptrR = gain(gainR, *ptrR); + ptrL += 2; ptrR += 2; + } } } diff --git a/output_pulse.c b/output_pulse.c index 69e194d..274380d 100644 --- a/output_pulse.c +++ b/output_pulse.c @@ -362,8 +362,9 @@ d->default_sink_name = strdup(l->name); if (!d->userdef_rates) { - d->rates[0] = l->sample_spec.rate; - } + d->rates[0] = PA_RATE_MAX; + } + output.default_sample_rate = l->sample_spec.rate; *d->sample_spec = l->sample_spec; } @@ -386,7 +387,7 @@ return true; } -static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, +static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) { pa_stream_write(pulse.stream, silence ? silencebuf : outputbuf->readp, out_frames * BYTES_PER_FRAME, (pa_free_cb_t)NULL, 0, PA_SEEK_RELATIVE); return (int)out_frames; diff --git a/output_stdout.c b/output_stdout.c index 640a883..036f700 100644 --- a/output_stdout.c +++ b/output_stdout.c @@ -45,7 +45,7 @@ static unsigned buffill; static int bytes_per_frame; -static int _stdout_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, +static int _stdout_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) { u8_t *obuf; @@ -75,7 +75,7 @@ } ) - _scale_and_pack_frames(buf + buffill * bytes_per_frame, (s32_t *)(void *)obuf, out_frames, gainL, gainR, output.format); + _scale_and_pack_frames(buf + buffill * bytes_per_frame, (s32_t *)(void *)obuf, out_frames, gainL, gainR, flags, output.format); buffill += out_frames; diff --git a/pcm.c b/pcm.c index 83d4e61..ac609f6 100644 --- a/pcm.c +++ b/pcm.c @@ -63,7 +63,7 @@ #define MAX_DECODE_FRAMES 4096 static u32_t sample_rates[] = { - 11025, 22050, 32000, 44100, 48000, 8000, 12000, 16000, 24000, 96000, 88200, 176400, 192000, 352800, 384000, 705600, 768000 + 11025, 22050, 32000, 44100, 48000, 8000, 12000, 16000, 24000, 96000, 88200, 176400, 192000, 352800, 384000, 705600, 768000, 1411200, 1536000 }; static u32_t sample_rate; diff --git a/slimproto.c b/slimproto.c index edc6bff..d81f512 100644 --- a/slimproto.c +++ b/slimproto.c @@ -120,7 +120,7 @@ } static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t mac[6]) { - #define BASE_CAP "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION + #define BASE_CAP "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Balance=1,Firmware=" VERSION #define SSL_CAP "CanHTTPS=1" const char *base_cap; struct HELO_packet pkt; @@ -380,7 +380,8 @@ output.fade_mode = strm->transition_type - '0'; output.fade_secs = strm->transition_period; output.invert = (strm->flags & 0x03) == 0x03; - LOG_DEBUG("set fade mode: %u", output.fade_mode); + output.channels = (strm->flags & 0x0c) >> 2; + LOG_DEBUG("set fade mode: %u, channels: %u, invert: %u", output.fade_mode, output.channels, output.invert); UNLOCK_O; } break; @@ -875,7 +876,11 @@ LOCK_O; snprintf(fixed_cap, FIXED_CAP_LEN, ",ModelName=%s,MaxSampleRate=%u", modelname ? modelname : MODEL_NAME_STRING, +#if RESAMPLE ((maxSampleRate > 0) ? maxSampleRate : output.supported_rates[0])); +#else + ((maxSampleRate > 0 && maxSampleRate < output.supported_rates[0]) ? maxSampleRate : output.supported_rates[0])); +#endif for (i = 0; i < MAX_CODECS; i++) { if (codecs[i] && codecs[i]->id && strlen(fixed_cap) < FIXED_CAP_LEN - 10) { diff --git a/squeezelite.h b/squeezelite.h index fd89073..1d25c51 100644 --- a/squeezelite.h +++ b/squeezelite.h @@ -25,8 +25,8 @@ // make may define: PORTAUDIO, SELFPIPE, RESAMPLE, RESAMPLE_MP, VISEXPORT, GPIO, IR, DSD, LINKALL to influence build #define MAJOR_VERSION "1.9" -#define MINOR_VERSION "8" -#define MICRO_VERSION "1317" +#define MINOR_VERSION "9" +#define MICRO_VERSION "1411" #if defined(CUSTOM_VERSION) #define VERSION "v" MAJOR_VERSION "." MINOR_VERSION "-" MICRO_VERSION STR(CUSTOM_VERSION) @@ -615,12 +615,15 @@ typedef enum { FADE_UP = 1, FADE_DOWN, FADE_CROSS } fade_dir; typedef enum { FADE_NONE = 0, FADE_CROSSFADE, FADE_IN, FADE_OUT, FADE_INOUT } fade_mode; -#define MAX_SUPPORTED_SAMPLERATES 18 -#define TEST_RATES = { 768000, 705600, 384000, 352800, 192000, 176400, 96000, 88200, 48000, 44100, 32000, 24000, 22500, 16000, 12000, 11025, 8000, 0 } +#define MONO_RIGHT 0x02 +#define MONO_LEFT 0x01 +#define MAX_SUPPORTED_SAMPLERATES 20 +#define TEST_RATES = { 1536000, 1411200, 768000, 705600, 384000, 352800, 192000, 176400, 96000, 88200, 48000, 44100, 32000, 24000, 22500, 16000, 12000, 11025, 8000, 0 } struct outputstate { output_state state; output_format format; + u8_t channels; const char *device; #if ALSA unsigned buffer; @@ -632,7 +635,7 @@ unsigned latency; int pa_hostapi_option; #endif - 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); + int (* write_cb)(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr); unsigned start_frames; unsigned frames_played; unsigned frames_played_dmp;// frames played at the point delay is measured @@ -716,9 +719,9 @@ void output_close_stdout(void); // output_pack.c -void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, output_format format); +void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, u8_t flags, output_format format); void _apply_cross(struct buffer *outputbuf, frames_t out_frames, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr); -void _apply_gain(struct buffer *outputbuf, frames_t count, s32_t gainL, s32_t gainR); +void _apply_gain(struct buffer *outputbuf, frames_t count, s32_t gainL, s32_t gainR, u8_t flags); s32_t gain(s32_t gain, s32_t sample); s32_t to_gain(float f); @@ -759,16 +762,15 @@ struct codec *register_opus(void); #endif -//gpio.c +// gpio.c #if GPIO -void relay( int state); +void relay(int state); void relay_script(int state); int gpio_pin; bool gpio_active_low; bool gpio_active; char *power_script; -// my amp state -int ampstate; + #if RPI #define PI_INPUT 0 #define PI_OUTPUT 1 diff --git a/squeezelite.vcproj b/squeezelite.vcproj index 13ab395..4cb483e 100755 --- a/squeezelite.vcproj +++ b/squeezelite.vcproj @@ -130,7 +130,7 @@ writep, space, 0); if (n == 0) { - LOG_INFO("end of stream"); + LOG_INFO("end of stream (%u bytes)", stream.bytes); _disconnect(DISCONNECT, DISCONNECT_OK); } - if (n < 0 && _last_error() != ERROR_WOULDBLOCK) { - LOG_INFO("error reading: %s", strerror(last_error())); - _disconnect(DISCONNECT, REMOTE_DISCONNECT); + if (n < 0) { + error = _last_error(); + if (error != ERROR_WOULDBLOCK) { + LOG_INFO("error reading: %s (%d)", strerror(error), error); + _disconnect(DISCONNECT, REMOTE_DISCONNECT); + } } if (n > 0) { @@ -557,7 +571,10 @@ *host = '\0'; p = strcasestr(header,"Host:"); - if (p) sscanf(p, "Host:%255[^:]", host); + if (p) { + sscanf(p, "Host:%255s", host); + if ((p = strchr(host, ':')) != NULL) *p = '\0'; + } port = ntohs(port); sock = connect_socket(use_ssl || port == 443); diff --git a/utils.c b/utils.c index ecaf02c..9b06476 100644 --- a/utils.c +++ b/utils.c @@ -489,7 +489,7 @@ } #endif -#if WIN && USE_SSL +#if WIN char *strcasestr(const char *haystack, const char *needle) { size_t length_needle; size_t length_haystack; diff --git a/vorbis.c b/vorbis.c index 50f02b6..c6883d7 100644 --- a/vorbis.c +++ b/vorbis.c @@ -236,7 +236,12 @@ // work backward to unpack samples (if needed) iptr = (s16_t *) write_buf + count; - optr = (ISAMPLE_T *) write_buf + frames * 2; + IF_DIRECT( + optr = (ISAMPLE_T *) outputbuf->writep + frames * 2; + ) + IF_PROCESS( + optr = (ISAMPLE_T *) write_buf + frames * 2; + ) if (channels == 2) { #if BYTES_PER_FRAME == 4