head 1.4; access; symbols pkgsrc-2026Q1:1.4.0.38 pkgsrc-2026Q1-base:1.4 pkgsrc-2025Q4:1.4.0.36 pkgsrc-2025Q4-base:1.4 pkgsrc-2025Q3:1.4.0.34 pkgsrc-2025Q3-base:1.4 pkgsrc-2025Q2:1.4.0.32 pkgsrc-2025Q2-base:1.4 pkgsrc-2025Q1:1.4.0.30 pkgsrc-2025Q1-base:1.4 pkgsrc-2024Q4:1.4.0.28 pkgsrc-2024Q4-base:1.4 pkgsrc-2024Q3:1.4.0.26 pkgsrc-2024Q3-base:1.4 pkgsrc-2024Q2:1.4.0.24 pkgsrc-2024Q2-base:1.4 pkgsrc-2024Q1:1.4.0.22 pkgsrc-2024Q1-base:1.4 pkgsrc-2023Q4:1.4.0.20 pkgsrc-2023Q4-base:1.4 pkgsrc-2023Q3:1.4.0.18 pkgsrc-2023Q3-base:1.4 pkgsrc-2023Q2:1.4.0.16 pkgsrc-2023Q2-base:1.4 pkgsrc-2023Q1:1.4.0.14 pkgsrc-2023Q1-base:1.4 pkgsrc-2022Q4:1.4.0.12 pkgsrc-2022Q4-base:1.4 pkgsrc-2022Q3:1.4.0.10 pkgsrc-2022Q3-base:1.4 pkgsrc-2022Q2:1.4.0.8 pkgsrc-2022Q2-base:1.4 pkgsrc-2022Q1:1.4.0.6 pkgsrc-2022Q1-base:1.4 pkgsrc-2021Q4:1.4.0.4 pkgsrc-2021Q4-base:1.4 pkgsrc-2021Q3:1.4.0.2 pkgsrc-2021Q3-base:1.4; locks; strict; comment @// @; 1.4 date 2021.09.12.06.04.44; author nia; state Exp; branches; next 1.3; commitid TAA2tgFq2za55D8D; 1.3 date 2021.09.10.11.14.05; author nia; state Exp; branches; next 1.2; commitid T4Rn7gidpgBeRo8D; 1.2 date 2021.09.09.22.41.43; author nia; state Exp; branches; next 1.1; commitid 8RKqn9KaICO9Hk8D; 1.1 date 2021.09.08.19.19.20; author nia; state Exp; branches; next ; commitid jk4xZF7wZEZwAb8D; desc @@ 1.4 log @jack: Work around "error: ::vfscanf has not been declared" on NetBSD 9.x @ text @$NetBSD: patch-netbsd_sun_JackSunAdapter.cpp,v 1.1 2021/09/08 19:19:20 nia Exp $ Add NetBSD support. --- netbsd/sun/JackSunAdapter.cpp.orig 2021-09-12 05:59:47.131738128 +0000 +++ netbsd/sun/JackSunAdapter.cpp @@@@ -0,0 +1,490 @@@@ +/* +Copyright (C) 2008 Grame & RTL 2008 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "JackSunAdapter.h" +#include "JackServerGlobals.h" +#include "JackEngineControl.h" +#include "memops.h" + +#include +#include +#include +#include +#include + +namespace Jack +{ + +inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; } + +static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits) +{ +#if 0 + switch (bits) { + + case 16: { + signed short *s16src = (signed short*)src; + s16src += channel; + sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1); + break; + } + case 24: { + signed int *s32src = (signed int*)src; + s32src += channel; + sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2); + break; + } + case 32: { + signed int *s32src = (signed int*)src; + s32src += channel; + sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2); + break; + } + } +#endif +} + +static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits) +{ +#if 0 + switch (bits) { + + case 16: { + signed short *s16dst = (signed short*)dst; + s16dst += channel; + sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now... + break; + } + case 24: { + signed int *s32dst = (signed int*)dst; + s32dst += channel; + sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now... + break; + } + case 32: { + signed int *s32dst = (signed int*)dst; + s32dst += channel; + sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); + break; + } + } +#endif +} + +JackSunAdapter::JackSunAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) + :JackAudioAdapterInterface(buffer_size, sample_rate) + ,fThread(this), + fInFD(-1), fOutFD(-1), fPrecision(SUN_DRIVER_DEF_BITS), + fRWMode(0), + fInputBufferSize(0), fOutputBufferSize(0), + fInputBuffer(NULL), fOutputBuffer(NULL) +{ + const JSList* node; + const jack_driver_param_t* param; + + fCaptureChannels = 2; + fPlaybackChannels = 2; + + strcpy(fCaptureDriverName, SUN_DRIVER_DEF_DEV); + strcpy(fPlaybackDriverName, SUN_DRIVER_DEF_DEV); + + for (node = params; node; node = jack_slist_next(node)) { + param = (const jack_driver_param_t*) node->data; + + switch (param->character) { + + case 'r': + SetAdaptedSampleRate(param->value.ui); + break; + + case 'p': + SetAdaptedBufferSize(param->value.ui); + break; + + case 'w': + fPrecision = param->value.i; + break; + + case 'i': + fCaptureChannels = param->value.ui; + break; + + case 'o': + fPlaybackChannels = param->value.ui; + break; + + case 'C': + fRWMode |= kRead; + if (strcmp(param->value.str, "none") != 0) { + strcpy(fCaptureDriverName, param->value.str); + } + break; + + case 'P': + fRWMode |= kWrite; + if (strcmp(param->value.str, "none") != 0) { + strcpy(fPlaybackDriverName, param->value.str); + } + break; + + case 'd': + fRWMode |= kRead; + fRWMode |= kWrite; + strcpy(fCaptureDriverName, param->value.str); + strcpy(fPlaybackDriverName, param->value.str); + break; + + case 'q': + fQuality = param->value.ui; + break; + + case 'g': + fRingbufferCurSize = param->value.ui; + fAdaptative = false; + break; + + } + } + + fRWMode |= kRead; + fRWMode |= kWrite; +} + +void JackSunAdapter::DisplayDeviceInfo() +{ +} + +int JackSunAdapter::OpenInput() +{ + struct audio_info info; + + if ((fInFD = open(fCaptureDriverName, O_RDONLY)) < 0) { + jack_error("JackSunAdapter::OpenInput failed to open device : %s@@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + +#ifdef AUDIO_GETFORMAT + if (fCaptureChannels == 0) { + if (ioctl(fInFD, AUDIO_GETFORMAT, &info) != -1) { + fCaptureChannels = info.record.channels; + } + } +#else + if (fCaptureChannels == 0) { + fCaptureChannels = 2; + } +#endif + + jack_log("JackSunAdapter::OpenInput input fInFD = %d", fInFD); + + AUDIO_INITINFO(&info); + info.record.encoding = AUDIO_ENCODING_SLINEAR; + info.record.precision = fPrecision; + info.record.channels = fCaptureChannels; + info.record.sample_rate = fAdaptedSampleRate; + + if (ioctl(fInFD, AUDIO_SETINFO, &info) == -1) { + jack_error("JackSunAdapter::OpenInput failed to set device parameters : %s@@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (ioctl(fInFD, AUDIO_GETINFO, &info) == -1) { + jack_error("JackSunAdapter::OpenInput failed to get device paramters : %s@@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (info.record.channels != fCaptureChannels) { + jack_info("JackSunAdapter::OpenInput driver forced the number of capture channels %u", info.record.channels); + goto error; + } + + if (info.record.sample_rate != fAdaptedSampleRate) { + jack_info("JackSunAdapter::OpenInput driver forced the sample rate %u", info.record.sample_rate); + } + + fInputBufferSize = info.blocksize; + fInputBuffer = (void*)calloc(fInputBufferSize, 1); + assert(fInputBuffer); + + fInputSampleBuffer = (float**)malloc(fCaptureChannels * sizeof(float*)); + assert(fInputSampleBuffer); + + for (int i = 0; i < fCaptureChannels; i++) { + fInputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float)); + assert(fInputSampleBuffer[i]); + } + return 0; + +error: + ::close(fInFD); + return -1; +} + +int JackSunAdapter::OpenOutput() +{ + struct audio_info info; + + if ((fOutFD = open(fPlaybackDriverName, O_WRONLY)) < 0) { + jack_error("JackSunAdapter::OpenOutput failed to open device : %s@@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + +#ifdef AUDIO_GETFORMAT + if (fPlaybackChannels == 0) { + if (ioctl(fOutFD, AUDIO_GETFORMAT, &info) == 0) { + fPlaybackChannels = info.play.channels; + } + } +#else + if (fPlaybackChannels == 0) { + fPlaybackChannels = 2; + } +#endif + + jack_log("JackSunAdapter::OpenOutput input fOutFD = %d", fOutFD); + + AUDIO_INITINFO(&info); + info.hiwat = 2; + info.play.encoding = AUDIO_ENCODING_SLINEAR; + info.play.precision = fPrecision; + info.play.channels = fPlaybackChannels; + info.play.sample_rate = fAdaptedSampleRate; + + if (ioctl(fOutFD, AUDIO_SETINFO, &info) == -1) { + jack_error("JackSunAdapter::OpenOutput failed to set device parameters : %s@@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (ioctl(fOutFD, AUDIO_GETINFO, &info) == -1) { + jack_error("JackSunAdapter::OpenOutput failed to get device paramters : %s@@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (info.play.precision != fPrecision) { + jack_info("JackSunAdapter::OpenOutput driver forced the precision %u", info.play.precision); + goto error; + } + + if (info.play.channels != fPlaybackChannels) { + jack_info("JackSunAdapter::OpenOutput driver forced the number of capture channels %u", info.play.channels); + goto error; + } + + if (info.play.sample_rate != fAdaptedSampleRate) { + jack_info("JackSunAdapter::OpenOutput driver forced the sample rate %u", info.play.sample_rate); + } + + fOutputBufferSize = info.blocksize; + fOutputBuffer = (void*)calloc(fOutputBufferSize, 1); + assert(fOutputBuffer); + + fOutputSampleBuffer = (float**)malloc(fPlaybackChannels * sizeof(float*)); + assert(fOutputSampleBuffer); + + for (int i = 0; i < fPlaybackChannels; i++) { + fOutputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float)); + assert(fOutputSampleBuffer[i]); + } + + return 0; + +error: + ::close(fOutFD); + return -1; +} + +int JackSunAdapter::Open() +{ + if ((fRWMode & kRead) && (OpenInput() < 0)) { + return -1; + } + + if ((fRWMode & kWrite) && (OpenOutput() < 0)) { + return -1; + } + + // In duplex mode, check that input and output use the same buffer size + if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) { + jack_error("JackSunAdapter::OpenAux input and output buffer size are not the same!!"); + goto error; + } + + DisplayDeviceInfo(); + + //start adapter thread + if (fThread.StartSync() < 0) { + jack_error ( "Cannot start audioadapter thread" ); + return -1; + } + + //turn the thread realtime + fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority); + return 0; + +error: + CloseAux(); + return -1; +} + + +int JackSunAdapter::Close() +{ +#ifdef JACK_MONITOR + fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); +#endif + fThread.Stop(); + CloseAux(); + return 0; +} + +void JackSunAdapter::CloseAux() +{ + if (fRWMode & kRead) { + close(fInFD); + fInFD = -1; + } + + if (fRWMode & kWrite) { + close(fOutFD); + fOutFD = -1; + } + + free(fInputBuffer); + fInputBuffer = NULL; + + free(fOutputBuffer); + fOutputBuffer = NULL; + + for (int i = 0; i < fCaptureChannels; i++) { + free(fInputSampleBuffer[i]); + } + free(fInputSampleBuffer); + + for (int i = 0; i < fPlaybackChannels; i++) { + free(fOutputSampleBuffer[i]); + } + free(fOutputSampleBuffer); + } + +int JackSunAdapter::Read() +{ + ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize); + + if (count < fInputBufferSize) { + jack_error("JackSunAdapter::Read error bytes read = %ld", count); + return -1; + } else { + for (int i = 0; i < fCaptureChannels; i++) { + CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fPrecision); + } + return 0; + } +} + +int JackSunAdapter::Write() +{ + ssize_t count; + + for (int i = 0; i < fPlaybackChannels; i++) { + CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fPrecision); + } + + count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); + + if (count < fOutputBufferSize) { + jack_error("JackSunAdapter::Write error bytes written = %ld", count); + return -1; + } else { + return 0; + } +} + +bool JackSunAdapter::Execute() +{ + //read data from audio interface + if (Read() < 0) + return false; + + PushAndPull(fInputSampleBuffer, fOutputSampleBuffer, fAdaptedBufferSize); + + //write data to audio interface + if (Write() < 0) + return false; + + return true; +} + +int JackSunAdapter::SetBufferSize(jack_nframes_t buffer_size) +{ + JackAudioAdapterInterface::SetBufferSize(buffer_size); + Close(); + return Open(); +} + +} // namespace + +#ifdef __cplusplus +extern "C" +{ +#endif + + SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() + { + jack_driver_desc_t * desc; + jack_driver_desc_filler_t filler; + jack_driver_param_value_t value; + + desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler); + + value.ui = SUN_DRIVER_DEF_FS; + jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); + + value.ui = SUN_DRIVER_DEF_BLKSIZE; + jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL); + + value.i = SUN_DRIVER_DEF_BITS; + jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL); + + value.ui = SUN_DRIVER_DEF_INS; + jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL); + + value.ui = SUN_DRIVER_DEF_OUTS; + jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL); + + strcpy(value.str, SUN_DRIVER_DEF_DEV); + jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL); + jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL); + jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "Audio device name", NULL); + + value.i = true; + jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL); + + value.ui = 0; + jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); + + value.i = 32768; + jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)"); + + return desc; + } + +#ifdef __cplusplus +} +#endif + @ 1.3 log @jack: Install man pages on non-Linux. Fix Linux PLIST. @ text @d5 1 a5 1 --- netbsd/sun/JackSunAdapter.cpp.orig 2021-09-10 11:08:26.064717543 +0000 @ 1.2 log @jack: support systems without AUDIO_GETFORMAT (NetBSD 8) @ text @d5 1 a5 1 --- netbsd/sun/JackSunAdapter.cpp.orig 2021-09-09 21:08:54.598607823 +0000 @ 1.1 log @jack: Update to 1.9.19 This switches us to jack2, the latest rewrite of the JACK audio server, with support for Solaris, Linux, macOS, and NetBSD (support for NetBSD added by me in a series of patches...) My primary motivation for this update is to avoid jack1's unpleasant abuse of unix domain sockets such that it no longer works in NetBSD 9.99.x (see PR kern/56113) @ text @d1 1 a1 1 $NetBSD$ d5 1 a5 1 --- netbsd/sun/JackSunAdapter.cpp.orig 2021-09-08 13:51:19.685213690 +0000 d7 1 a7 1 @@@@ -0,0 +1,478 @@@@ d189 1 d195 5 d255 1 d261 5 @