From cc383dbf85dca127e98a768de8c93e0410928c61 Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Mon, 30 Jan 2023 22:04:50 +0100 Subject: [PATCH 01/44] Release 0.6.0 --- NEWS | 20 ++++++++++++++++++++ doc/manual/conf.py | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index df0ba844..1df69ec2 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,25 @@ User-visible changes in the SoundScape Renderer. Recent changes on top. +0.6.0 (31 January 2023) + + - 3D support for the binaural renderer using SOFA files + + - new network interfaces: WebSocket and FUDI + + - an experimental browser-based 3D GUI (using the WebSocket interface) + + - Qt GUI: + - drag & drop of scene files to GUI + - close with Ctrl-q instead of Esc + + - Pd externals: path handling has been fixed, BRS renderer is now also available + + - macOS: No pre-compiled App Bundle will be provided, + the possibility for building it locally might be removed in a future version + + - The "ssr" script has been removed, use ssr-binaural, ssr-brs, ssr-vbap, + ssr-wfs, ssr-aap, ssr-dca or ssr-generic instead. + 0.5.0 (16 November 2018) - GUI now uses Qt5 diff --git a/doc/manual/conf.py b/doc/manual/conf.py index 24095c8a..62c77660 100644 --- a/doc/manual/conf.py +++ b/doc/manual/conf.py @@ -12,7 +12,7 @@ master_doc = 'index' project = u'SoundScape Renderer' -copyright = u'2022, SSR Team' +copyright = u'2023, SSR Team' try: release = check_output(['git', 'describe', '--tags', '--always']) From 0bd57f526f5d00841951d27d5aa469a39d528b12 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 13:57:09 +0200 Subject: [PATCH 02/44] Make 0.6.0 compile on windows --- CMakeLists.txt | 311 +++++++ extern/include/bits/fcntl2.h | 297 ++++++ extern/include/bits/termios.h | 219 +++++ extern/include/jack/control.h | 631 +++++++++++++ extern/include/jack/intclient.h | 130 +++ extern/include/jack/jack.h | 1470 ++++++++++++++++++++++++++++++ extern/include/jack/jslist.h | 293 ++++++ extern/include/jack/midiport.h | 184 ++++ extern/include/jack/ringbuffer.h | 243 +++++ extern/include/jack/session.h | 270 ++++++ extern/include/jack/statistics.h | 57 ++ extern/include/jack/systemdeps.h | 126 +++ extern/include/jack/thread.h | 160 ++++ extern/include/jack/transport.h | 247 +++++ extern/include/jack/types.h | 740 +++++++++++++++ extern/include/jack/weakjack.h | 125 +++ extern/include/jack/weakmacros.h | 97 ++ extern/include/termios.h | 656 +++++++++++++ extern/include/unistd_extra.h | 100 ++ extern/lib/libjack64.lib | Bin 0 -> 41990 bytes extern/lib/libjackserver64.lib | Bin 0 -> 376052 bytes generate_config.h.in | 56 ++ src/controller.h | 6 +- src/pathtools.h | 2 +- src/razor-ahrs/RazorAHRS.h | 13 + src/trackerpolhemus.cpp | 28 +- 26 files changed, 6455 insertions(+), 6 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 extern/include/bits/fcntl2.h create mode 100644 extern/include/bits/termios.h create mode 100644 extern/include/jack/control.h create mode 100644 extern/include/jack/intclient.h create mode 100644 extern/include/jack/jack.h create mode 100644 extern/include/jack/jslist.h create mode 100644 extern/include/jack/midiport.h create mode 100644 extern/include/jack/ringbuffer.h create mode 100644 extern/include/jack/session.h create mode 100644 extern/include/jack/statistics.h create mode 100644 extern/include/jack/systemdeps.h create mode 100644 extern/include/jack/thread.h create mode 100644 extern/include/jack/transport.h create mode 100644 extern/include/jack/types.h create mode 100644 extern/include/jack/weakjack.h create mode 100644 extern/include/jack/weakmacros.h create mode 100644 extern/include/termios.h create mode 100644 extern/include/unistd_extra.h create mode 100644 extern/lib/libjack64.lib create mode 100644 extern/lib/libjackserver64.lib create mode 100644 generate_config.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..4f738322 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,311 @@ +# run e.g.: mkdir -p _build && cd _build && cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make -j3 && cd .. +# Specify the minimum version for CMake +message(STATUS "CMAKE_VERSION: " ${CMAKE_VERSION}) +cmake_minimum_required(VERSION 3.8) + +# Project's name +project(SSR) + +# The version number +set(SSR_VERSION 0.5.1-cmake) + +# Show more of make +set(CMAKE_VERBOSE_MAKEFILE ON) + +# Set the output folder where your program will be created +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/_build) +if(WIN32) + set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) +else(WIN32) + set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/src) +endif(WIN32) + +# Show the compiler +message(STATUS "Comiler: " ${CMAKE_CXX_COMPILER}) +message(STATUS "Compiler ID: " ${CMAKE_CXX_COMPILER_ID}) + +# Enable C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# The following folders will be included +include_directories(${PROJECT_SOURCE_DIR}/src) + +# Include APF +set(APF_PATH ${PROJECT_SOURCE_DIR}/apf) +include_directories(${APF_PATH}) + +# Include GML +set(GML_PATH ${PROJECT_SOURCE_DIR}/gml/include) +include_directories(${GML_PATH}) + +# Files +set(SOURCE_FILES + src/configuration.cpp + src/ssr_global.cpp + src/xmlparser.cpp + src/legacy_directionalpoint.cpp + src/legacy_orientation.cpp + src/legacy_position.cpp + src/legacy_scene.cpp + ) + +# Libraries +# Add libraries to LINKLIBS +set(LINKLIBS) + +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads REQUIRED) + +# TODO +find_package(PkgConfig REQUIRED) + +if(WIN32) + # Set Path to extern headers and libraries for Windows builds + set(EXTERN_PATH ${PROJECT_SOURCE_DIR}/extern) + set(CMAKE_PREFIX_PATH ${EXTERN_PATH}) + message(STATUS "WINDOWS Prefix: " ${CMAKE_PREFIX_PATH}) + + # Include extern headers + include_directories(${EXTERN_PATH}/include) + message(STATUS "WINDOWS Included: " ${EXTERN_PATH}/include) + + # here is the target environment located + set (CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${EXTERN_PATH}) +endif(WIN32) + +if(WIN32) + # Use custom static libxml2 build for MSVC + #if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # find_library(LibXml2 NAMES libxml2_msvc) + #endif() + find_package(LibXml2 REQUIRED) + include_directories(${LIBXML2_INCLUDE_DIR}) + list(APPEND LINKLIBS ${LIBXML2_LIBRARY}) + add_definitions(-DLIBXML_STATIC) + #list(APPEND LINKLIBS "-lxml2 -lz -llzma -lws2_32") + list(APPEND LINKLIBS "-llzma") + message(STATUS "Found XML2: " ${LIBXML2_LIBRARY}) + message(STATUS "Found XML2 headers: " ${LIBXML2_INCLUDE_DIR}) +else(WIN32) + find_package(LibXml2 REQUIRED) + include_directories(${LIBXML2_INCLUDE_DIR}) + list(APPEND LINKLIBS ${LIBXML2_LIBRARY}) +endif(WIN32) + +find_library(LIBSNDFILE_LIBRARY NAMES sndfile libsndfile-1) +list(APPEND LINKLIBS ${LIBSNDFILE_LIBRARY}) +list(APPEND LINKLIBS -lFLAC -lopus -lvorbisenc -lvorbis -logg) +message(STATUS "Found SNDFILE: " ${LIBSNDFILE_LIBRARY}) + +option(ENABLE_ECASOUND "Ecasound soundfile playback/recording" OFF) +if(ENABLE_ECASOUND) + list(APPEND SOURCE_FILES + src/audioplayer.cpp + src/audiorecorder.cpp + ) + find_path(ECASOUND_INCLUDE_DIR NAMES ecasoundc.h HINTS /usr/include/libecasoundc) + include_directories(${ECASOUND_INCLUDE_DIR}) + find_library(ECASOUND_LIBRARY NAMES ecasoundc) + list(APPEND LINKLIBS ${ECASOUND_LIBRARY}) + message(STATUS "Found ECASOUND: " ${ECASOUND_LIBRARY}) +else(ENABLE_ECASOUND) + message(WARNING "ECASOUND disabled.") +endif(ENABLE_ECASOUND) + +find_library(JACK_LIBRARY NAMES jack libjack64) +list(APPEND LINKLIBS ${JACK_LIBRARY}) +message(STATUS "Found JACK :" ${JACK_LIBRARY}) + +if(WIN32) + find_library(JACKSERVER_LIBRARY NAMES libjackserver64) + list(APPEND LINKLIBS ${JACKSERVER_LIBRARY}) + message(STATUS "Found JACK :" ${JACKSERVER_LIBRARY}) +endif(WIN32) + +find_library(FFTW_LIBRARY NAMES fftw3 libfftw3-3) +list(APPEND LINKLIBS ${FFTW_LIBRARY}) +message(STATUS "Found FFTW: " ${FFTW_LIBRARY}) + +find_library(FFTWF_LIBRARY NAMES fftw3f libfftw3f-3) +list(APPEND LINKLIBS ${FFTWF_LIBRARY}) +message(STATUS "Found FFTWF: " ${FFTWF_LIBRARY}) + +# GUI +option(GUI "Build GUI" ON) +if(GUI) + # Find includes in corresponding build directories + set(CMAKE_INCLUDE_CURRENT_DIR ON) + # Turn on automatic invocation of the MOC + set(CMAKE_AUTOMOC ON) + + include_directories(${PROJECT_SOURCE_DIR}/src/gui) # necessary? + #set(GUI_SOURCE_FILES + # src/gui/qclicktextlabel.cpp + # src/gui/qcpulabel.cpp + # src/gui/qfilemenulabel.cpp + # src/gui/qgui.cpp + # src/gui/qguiframe.cpp + # src/gui/qopenglplotter.cpp + # src/gui/qscenebutton.cpp + # src/gui/qsourceproperties.cpp + # src/gui/qssrtimeline.cpp + # src/gui/qtimeedit.cpp + # src/gui/quserinterface.cpp + # src/gui/qvolumeslider.cpp + # src/gui/qzoomlabel.cpp + # ) + AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src/gui GUI_SOURCE_FILES) + list(APPEND SOURCE_FILES ${GUI_SOURCE_FILES}) + + option(ENABLE_GUI "graphical user interface (using Qt)" ON) + option(ENABLE_FLOATING_CONTROL_PANEL "separate control window" ON) + option(STATIC_QT "Use static Qt5 libraries (Windows)" ON) + + find_package(Qt5 COMPONENTS Core Gui Widgets OpenGL REQUIRED) + message(STATUS "Found QT5: " ${Qt5_DIR}) + + if(WIN32) + if(STATIC_QT) + add_definitions(-DQT_STATICPLUGIN) + endif(STATIC_QT) + + # Platform support libs for Windows + set(QT5PLATFORMSUPPORT_LIBS + Qt5::QWindowsIntegrationPlugin + ) + + # Qt5PlatformSupport modules + find_library(Qt5ThemeSupport_LIBRARY Qt5ThemeSupport) + list(APPEND QT5PLATFORMSUPPORT_LIBS ${Qt5ThemeSupport_LIBRARY}) + find_library(Qt5FontDatabaseSupport_LIBRARY Qt5FontDatabaseSupport) + list(APPEND QT5PLATFORMSUPPORT_LIBS ${Qt5FontDatabaseSupport_LIBRARY}) + find_library(Qt5EventDispatcherSupport_LIBRARY Qt5EventDispatcherSupport) + list(APPEND QT5PLATFORMSUPPORT_LIBS ${Qt5EventDispatcherSupport_LIBRARY}) + find_library(Qt5AccessibilitySupport_LIBRARY Qt5AccessibilitySupport) + list(APPEND QT5PLATFORMSUPPORT_LIBS ${Qt5AccessibilitySupport_LIBRARY}) + find_library(Qt5WindowsUIAutomationSupport_LIBRARY Qt5WindowsUIAutomationSupport) + list(APPEND QT5PLATFORMSUPPORT_LIBS ${Qt5WindowsUIAutomationSupport_LIBRARY}) + + find_package(Freetype REQUIRED) + list(APPEND QT5PLATFORMSUPPORT_LIBS ${FREETYPE_LIBRARIES}) + + list(APPEND QT5PLATFORMSUPPORT_LIBS "-lwtsapi32") + + message(STATUS "Found Qt5PlatformSupport: " ${QT5PLATFORMSUPPORT_LIBS}) + endif(WIN32) + + # OpenGL + find_package(OpenGL REQUIRED) + include_directories(${OPENGL_INCLUDE_DIR}) + list(APPEND LINKLIBS ${OPENGL_gl_LIBRARY}) + list(APPEND LINKLIBS ${OPENGL_glu_LIBRARY}) + + message(STATUS "Build GUI") + +else(GUI) + message(WARNING "GUI disabled. Switch on with 'cmake .. -DGUI=ON'") +endif(GUI) + +# Network +option(ENABLE_IP_INTERFACE "network (TCP/IP) interface (legacy)" ON) +if(ENABLE_IP_INTERFACE) + #list(APPEND SOURCE_FILES + # src/network/commandparser.cpp + # src/network/connection.cpp + # src/network/networksubscriber.cpp + # src/network/server.cpp + # ) + AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src/legacy_network NETWORK_SOURCE_FILES) + list(APPEND SOURCE_FILES ${NETWORK_SOURCE_FILES}) + + include_directories(${PROJECT_SOURCE_DIR}/src/legacy_network) + add_definitions(-DASIO_STANDALONE) + if(WIN32) + add_definitions(-D_WIN32_WINNT=0x0601) # Windows 7 + list(APPEND LINKLIBS "-lws2_32 -lmswsock") + endif(WIN32) + message(STATUS "Enabled network interface (legacy)") + +else(ENABLE_IP_INTERFACE) + message(WARNING "IP_INTERFACE disabled.") +endif(ENABLE_IP_INTERFACE) + +# Head tracker +option(HEAD_TRACKER "Basic head tracker support" ON) +if(HEAD_TRACKER) + list(APPEND SOURCE_FILES + src/trackerrazor.cpp + src/razor-ahrs/RazorAHRS.cpp + src/trackerpolhemus.cpp + ) + set(ENABLE_RAZOR ON) + set(ENABLE_POLHEMUS ON) + if(WIN32) + add_definitions(-DENABLE_O_NDELAY_WORKAROUND) # bits/fcntl2.h + endif(WIN32) + message(STATUS "Basic head tracker support") +else(HEAD_TRACKER) + message(WARNING "HEAD_TRACKER disabled.") +endif(HEAD_TRACKER) + + +# Preprocessor symbols +add_definitions(-DSSR_DATA_DIR="./data") + +# Config definitions +# configure a header file to pass some of the CMake settings +# to the source code +add_definitions(-DHAVE_CONFIG_H) +configure_file( + "${PROJECT_SOURCE_DIR}/generate_config.h.in" + "${PROJECT_SOURCE_DIR}/src/config.h" + ) + + +# Compiler flags +# Add a few for release builds (MAKE_BUILD_TYPE=RELEASE) +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pipe -Wall -fomit-frame-pointer -ffast-math -funroll-loops -march=x86-64 -mmmx -msse -msse2 -mfpmath=sse") +message(STATUS "Release Flags: " ${CMAKE_CXX_FLAGS_RELEASE}) +# And for debug builds (MAKE_BUILD_TYPE=DEBUG) +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pipe -Wall -ffast-math -march=x86-64 -mmmx -msse -msse2 -mfpmath=sse -Weffc++") +message(STATUS "Debug Flags: " ${CMAKE_CXX_FLAGS_DEBUG}) + +# Compile executables +set(EXECUTABLES + ssr-binaural + ssr-brs + ssr-vbap + ssr-wfs + ssr-aap + ssr-dca + ssr-generic + ) +add_executable(ssr-binaural src/ssr_binaural.cpp ${SOURCE_FILES}) +add_executable(ssr-brs src/ssr_brs.cpp ${SOURCE_FILES}) +add_executable(ssr-vbap src/ssr_vbap.cpp ${SOURCE_FILES}) +add_executable(ssr-wfs src/ssr_wfs.cpp ${SOURCE_FILES}) +add_executable(ssr-aap src/ssr_aap.cpp ${SOURCE_FILES}) +add_executable(ssr-dca src/ssr_dca.cpp ${SOURCE_FILES}) +add_executable(ssr-generic src/ssr_generic.cpp ${SOURCE_FILES}) + + +# Link +if(WIN32) + set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") +endif(WIN32) + +message(STATUS "Linking: " ${LINKLIBS} ${QT5PLATFORMSUPPORT_LIBS}) + +foreach(executable ${EXECUTABLES}) + target_link_libraries(${executable} Threads::Threads stdc++fs) + target_link_libraries(${executable} ${LINKLIBS}) + if(GUI) + target_link_libraries(${executable} Qt5::Gui Qt5::Core Qt5::Widgets Qt5::OpenGL ${QT5PLATFORMSUPPORT_LIBS}) + qt5_import_plugins(${executable} INCLUDE Qt5::Gui Qt5::Core Qt5::Widgets Qt5::OpenGL ${QT5PLATFORMSUPPORT_LIBS}) + qt5_import_plugins(${executable} INCLUDE_BY_TYPE platforms) + + endif(GUI) +endforeach(executable ${EXECUTABLES}) diff --git a/extern/include/bits/fcntl2.h b/extern/include/bits/fcntl2.h new file mode 100644 index 00000000..b2386594 --- /dev/null +++ b/extern/include/bits/fcntl2.h @@ -0,0 +1,297 @@ +#ifndef FCNCTL2_H +#define FCNCTL2_H + +// Prevent Winsock.h from being included by the Windows.h header. +// This must be done if we plan to include Winsock2.h in other files. +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif // WIN32_LEAN_AND_MEAN +#include + +#include + +#include +#include +#include + +#ifdef _MSC_VER +// Disable some Visual Studio warnings. +#pragma warning(disable : 4996) +#endif // _MSC_VER + +/* open/fcntl. */ +#ifndef O_NOCTTY +# define O_NOCTTY 0400 /* Not fcntl. */ +#endif +//#ifndef O_TRUNC +//# define O_TRUNC 01000 /* Not fcntl. */ +//#endif +//#ifndef O_APPEND +//# define O_APPEND 02000 +//#endif +#ifndef O_NONBLOCK +# define O_NONBLOCK 04000 +#endif +#ifndef O_NDELAY +# define O_NDELAY O_NONBLOCK +#endif + +#ifndef __O_DIRECTORY +# define __O_DIRECTORY 0200000 +#endif +#ifndef __O_NOFOLLOW +# define __O_NOFOLLOW 0400000 +#endif +#ifndef __O_CLOEXEC +# define __O_CLOEXEC 02000000 +#endif +#ifndef __O_DIRECT +# define __O_DIRECT 040000 +#endif +#ifndef __O_NOATIME +# define __O_NOATIME 01000000 +#endif +#ifndef __O_PATH +# define __O_PATH 010000000 +#endif +#ifndef __O_TMPFILE +# define __O_TMPFILE (020000000 | __O_DIRECTORY) +#endif + +# define O_DIRECTORY __O_DIRECTORY /* Must be a directory. */ +# define O_NOFOLLOW __O_NOFOLLOW /* Do not follow links. */ +# define O_CLOEXEC __O_CLOEXEC /* Set close_on_exec. */ + +# define O_DIRECT __O_DIRECT /* Direct disk access. */ +# define O_NOATIME __O_NOATIME /* Do not set atime. */ +# define O_PATH __O_PATH /* Resolve pathname but do not open file. */ +# define O_TMPFILE __O_TMPFILE /* Atomically create nameless file. */ + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ + +#define MAX_PATH_LENGTH_OPEN_LINUX (128-8) + +// Very limited implementation... +__inline int fcntl(int __fd, int __cmd, ...) +{ + HANDLE hDev = (HANDLE)(intptr_t)__fd; + COMMTIMEOUTS timeouts; + // Disable if XON/XOFF are necessary, enable if fcntl() is used together with O_NDELAY and timeouts... +#ifdef ENABLE_O_NDELAY_WORKAROUND + DCB dcb; + DWORD ReadIntervalTimeout = 0, ReadTotalTimeoutConstant = 0, ReadTotalTimeoutMultiplier = 0, WriteTotalTimeoutConstant = 0; +#endif // ENABLE_O_NDELAY_WORKAROUND + va_list argptr; + va_start(argptr, __cmd); + + if (__cmd == F_SETFL) + { + int flags = va_arg(argptr, int); + + memset(&timeouts, 0, sizeof(COMMTIMEOUTS)); + if (!GetCommTimeouts(hDev, &timeouts)) + { + errno = EIO; + return -1; + } + if (flags & O_NDELAY) + { + // Disable if XON/XOFF are necessary, enable if fcntl() is used together with O_NDELAY and timeouts... +#ifdef ENABLE_O_NDELAY_WORKAROUND + // Need to save the original timeouts settings for next calls of fcntl()... + + memset(&dcb, 0, sizeof(DCB)); + if (!GetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } + + // Warning : XoffLim and XonLim are just used as placeholders to save the original timeouts settings, + // they are not normally related to timeouts... + + ReadIntervalTimeout = timeouts.ReadIntervalTimeout; + ReadTotalTimeoutConstant = timeouts.ReadTotalTimeoutConstant; + ReadTotalTimeoutMultiplier = timeouts.ReadTotalTimeoutMultiplier; + WriteTotalTimeoutConstant = timeouts.WriteTotalTimeoutConstant; + if (ReadIntervalTimeout == MAXDWORD) ReadIntervalTimeout = 255*100; + else if (ReadIntervalTimeout/100 > 254) ReadIntervalTimeout = 254*100; + if (ReadTotalTimeoutConstant == MAXDWORD) ReadTotalTimeoutConstant = 255*100; + else if (ReadTotalTimeoutConstant/100 > 254) ReadTotalTimeoutConstant = 254*100; + if (ReadTotalTimeoutMultiplier == MAXDWORD) ReadTotalTimeoutMultiplier = 255*100; + else if (ReadTotalTimeoutMultiplier/100 > 254) ReadTotalTimeoutMultiplier = 254*100; + if (WriteTotalTimeoutConstant == MAXDWORD) WriteTotalTimeoutConstant = 255*100; + else if (WriteTotalTimeoutConstant/100 > 254) WriteTotalTimeoutConstant = 254*100; + dcb.XoffLim = (WORD)(((ReadIntervalTimeout/100)<<8)|(ReadTotalTimeoutConstant/100)); + dcb.XonLim = (WORD)(((ReadTotalTimeoutMultiplier/100)<<8)|(WriteTotalTimeoutConstant/100)); + if (!SetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } +#endif // ENABLE_O_NDELAY_WORKAROUND + // Change timeout settings. + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 1; // ??? + timeouts.WriteTotalTimeoutMultiplier = 0; + if (!SetCommTimeouts(hDev, &timeouts)) + { + errno = EIO; + return -1; + } + } + else + { + // Disable if XON/XOFF are necessary, enable if fcntl() is used together with O_NDELAY and timeouts... +#ifdef ENABLE_O_NDELAY_WORKAROUND + // Should restore original timeout values... + + memset(&dcb, 0, sizeof(DCB)); + if (!GetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } + + // Warning : XoffLim and XonLim are just used as placeholders to save the original timeouts settings, + // they are not normally related to timeouts... + + if ((dcb.XoffLim>>8) == 255) timeouts.ReadIntervalTimeout = MAXDWORD; + else timeouts.ReadIntervalTimeout = (dcb.XoffLim>>8)*100; + if ((dcb.XoffLim&0x00FF) == 255) timeouts.ReadTotalTimeoutConstant = MAXDWORD; + else timeouts.ReadTotalTimeoutConstant = (dcb.XoffLim&0x00FF)*100; + if ((dcb.XonLim>>8) == 255) timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + else timeouts.ReadTotalTimeoutMultiplier = (dcb.XonLim>>8)*100; + if ((dcb.XonLim&0x00FF) == 255) timeouts.WriteTotalTimeoutConstant = MAXDWORD; + else timeouts.WriteTotalTimeoutConstant = (dcb.XonLim&0x00FF)*100; + timeouts.WriteTotalTimeoutMultiplier = 0; + // Set to full blocking in case the restored values were non-blocking. + if ((timeouts.ReadIntervalTimeout == MAXDWORD)&&(timeouts.ReadTotalTimeoutConstant == 0)&&(timeouts.ReadTotalTimeoutMultiplier == 0)) + { + timeouts.ReadIntervalTimeout = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + } +#else + timeouts.ReadIntervalTimeout = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; +#endif // ENABLE_O_NDELAY_WORKAROUND + if (!SetCommTimeouts(hDev, &timeouts)) + { + errno = EIO; + return -1; + } + } + } + else if (__cmd == F_GETFL) + { + int flags = 0; + + memset(&timeouts, 0, sizeof(COMMTIMEOUTS)); + if (!GetCommTimeouts(hDev, &timeouts)) + { + errno = EIO; + return -1; + } + if ((timeouts.ReadIntervalTimeout == MAXDWORD)&&(timeouts.ReadTotalTimeoutConstant == 0)&&(timeouts.ReadTotalTimeoutMultiplier == 0)) + { + // Polling read. + flags |= O_NDELAY; + } + else + { + // Blocking read. + flags &= ~O_NDELAY; + } + return flags; + } + + return 0; +} + +__inline int open_linux(const char *__path, int __oflag, ...) +{ + // The optional arguments are ignored... + + int fd = -1; + HANDLE hDev = INVALID_HANDLE_VALUE; + char szDeviceTemp[2*(MAX_PATH_LENGTH_OPEN_LINUX+8)]; + TCHAR tstr[2*(MAX_PATH_LENGTH_OPEN_LINUX+8)]; + DWORD dwDesiredAccess = 0; + DWORD dwCreationDisposition = 0; + DWORD dwShareMode = 0; + //SECURITY_ATTRIBUTES SecurityAttributes; + DWORD dwFlagsAndAttributes = 0; + + // To be able to use COM10 and greater we need to add "\\.\" (that becomes "\\\\.\\" + // in C because the '\' is a special character). + memset(szDeviceTemp, 0, sizeof(szDeviceTemp)); +//#ifdef WINCE + strcpy(szDeviceTemp, __path); +//#else +// sprintf(szDeviceTemp, "\\\\.\\%s", __path); +//#endif // WINCE + +#ifdef UNICODE + mbstowcs(tstr, szDeviceTemp, sizeof(szDeviceTemp)/2); +#else + memcpy(tstr, szDeviceTemp, sizeof(szDeviceTemp)/2); +#endif // UNICODE + tstr[sizeof(tstr)-1] = 0; + + if (__oflag & O_RDONLY) dwDesiredAccess |= GENERIC_READ; + if (__oflag & O_WRONLY) dwDesiredAccess |= GENERIC_WRITE; + if (__oflag & O_RDWR) dwDesiredAccess |= GENERIC_READ|GENERIC_WRITE; + + if (__oflag & O_APPEND) dwCreationDisposition |= OPEN_EXISTING; + if (__oflag & O_CREAT) + { + if (__oflag & O_EXCL) dwCreationDisposition |= CREATE_NEW; + else dwCreationDisposition |= CREATE_ALWAYS; + } + if (__oflag & O_TRUNC) dwCreationDisposition |= TRUNCATE_EXISTING; + + if ((__oflag & O_NONBLOCK)||(__oflag&O_NDELAY)) dwFlagsAndAttributes |= 0; // ? + + if (__oflag & O_DIRECT) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH; + + if (__oflag & O_TMPFILE) dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY; + + hDev = CreateFile(tstr, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); + + if (hDev == INVALID_HANDLE_VALUE) + { + errno = EIO; + return -1; + } + + //#ifndef DISABLE_FORCE_CLEAR_DTR + //if (!EscapeCommFunction(hDev, CLRDTR)) + //{ + // + //} + //#endif // DISABLE_FORCE_CLEAR_DTR + + fd = (int)(intptr_t)hDev; + + return fd; +} + +#ifdef _MSC_VER +// Restore the Visual Studio warnings previously disabled. +#pragma warning(default : 4996) +#endif // _MSC_VER + +#endif // FCNCTL2_H diff --git a/extern/include/bits/termios.h b/extern/include/bits/termios.h new file mode 100644 index 00000000..bbf093dc --- /dev/null +++ b/extern/include/bits/termios.h @@ -0,0 +1,219 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993-2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 +#ifdef __USE_MISC +# define EXTPROC 0200000 +#endif + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/extern/include/jack/control.h b/extern/include/jack/control.h new file mode 100644 index 00000000..33cd77b1 --- /dev/null +++ b/extern/include/jack/control.h @@ -0,0 +1,631 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + JACK control API + + Copyright (C) 2008 Nedko Arnaudov + Copyright (C) 2008 GRAME + + 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; version 2 of the License. + + 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. + +*/ +/** + * @file jack/control.h + * @ingroup publicheader + * @brief JACK control API + * + */ + +#ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED +#define JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED + +#include +#include +#include +#if !defined(sun) && !defined(__sun__) +#include +#endif + +/** Parameter types, intentionally similar to jack_driver_param_type_t */ +typedef enum +{ + JackParamInt = 1, /**< @brief value type is a signed integer */ + JackParamUInt, /**< @brief value type is an unsigned integer */ + JackParamChar, /**< @brief value type is a char */ + JackParamString, /**< @brief value type is a string with max size of ::JACK_PARAM_STRING_MAX+1 chars */ + JackParamBool, /**< @brief value type is a boolean */ +} jackctl_param_type_t; + +/** Driver types */ +typedef enum +{ + JackMaster = 1, /**< @brief master driver */ + JackSlave /**< @brief slave driver */ +} jackctl_driver_type_t; + +/** @brief Max value that jackctl_param_type_t type can have */ +#define JACK_PARAM_MAX (JackParamBool + 1) + +/** @brief Max length of string parameter value, excluding terminating null char */ +#define JACK_PARAM_STRING_MAX 127 + +/** @brief Type for parameter value */ +/* intentionally similar to jack_driver_param_value_t */ +union jackctl_parameter_value +{ + uint32_t ui; /**< @brief member used for ::JackParamUInt */ + int32_t i; /**< @brief member used for ::JackParamInt */ + char c; /**< @brief member used for ::JackParamChar */ + char str[JACK_PARAM_STRING_MAX + 1]; /**< @brief member used for ::JackParamString */ + bool b; /**< @brief member used for ::JackParamBool */ +}; + +/** opaque type for server object */ +typedef struct jackctl_server jackctl_server_t; + +/** opaque type for driver object */ +typedef struct jackctl_driver jackctl_driver_t; + +/** opaque type for internal client object */ +typedef struct jackctl_internal jackctl_internal_t; + +/** opaque type for parameter object */ +typedef struct jackctl_parameter jackctl_parameter_t; + +/** opaque type for sigmask object */ +typedef struct jackctl_sigmask jackctl_sigmask_t; + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} /* Adjust editor indent */ +#endif + +/** + * @defgroup ControlAPI The API for starting and controlling a JACK server + * @{ + */ + +/** + * Call this function to setup process signal handling. As a general + * rule, it is required for proper operation for the server object. + * + * @param flags signals setup flags, use 0 for none. Currently no + * flags are defined + * + * @return the configurated signal set. + */ +jackctl_sigmask_t * +jackctl_setup_signals( + unsigned int flags); + +/** + * Call this function to wait on a signal set. + * + * @param signals signals set to wait on + */ +void +jackctl_wait_signals( + jackctl_sigmask_t * signals); + +/** + * Call this function to create server object. + * + * @param on_device_acquire - Optional callback to be called before device is acquired. If false is returned, device usage will fail + * @param on_device_release - Optional callback to be called after device is released. + * + * @return server object handle, NULL if creation of server object + * failed. Successfully created server object must be destroyed with + * paired call to ::jackctl_server_destroy + */ +jackctl_server_t * +jackctl_server_create( + bool (* on_device_acquire)(const char * device_name), + void (* on_device_release)(const char * device_name)); + +/** + * Call this function to destroy server object. + * + * @param server server object handle to destroy + */ +void +jackctl_server_destroy( + jackctl_server_t * server); + +/** + * Call this function to open JACK server + * + * @param server server object handle + * @param driver driver to use + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_open( + jackctl_server_t * server, + jackctl_driver_t * driver); + +/** + * Call this function to start JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_start( + jackctl_server_t * server); + +/** + * Call this function to stop JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_stop( + jackctl_server_t * server); + +/** + * Call this function to close JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_close( + jackctl_server_t * server); + +/** + * Call this function to get list of available drivers. List node data + * pointers is a driver object handle (::jackctl_driver_t). + * + * @param server server object handle to get drivers for + * + * @return Single linked list of driver object handles. Must not be + * modified. Always same for same server object. + */ +const JSList * +jackctl_server_get_drivers_list( + jackctl_server_t * server); + +/** + * Call this function to get list of server parameters. List node data + * pointers is a parameter object handle (::jackctl_parameter_t). + * + * @param server server object handle to get parameters for + * + * @return Single linked list of parameter object handles. Must not be + * modified. Always same for same server object. + */ +const JSList * +jackctl_server_get_parameters( + jackctl_server_t * server); + +/** + * Call this function to get list of available internal clients. List node data + * pointers is a internal client object handle (::jackctl_internal_t). + * + * @param server server object handle to get internal clients for + * + * @return Single linked list of internal client object handles. Must not be + * modified. Always same for same server object. + */ +const JSList * +jackctl_server_get_internals_list( + jackctl_server_t * server); + +/** + * Call this function to load one internal client. + * (can be used when the server is running) + * + * @param server server object handle + * @param internal internal to use + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_load_internal( + jackctl_server_t * server, + jackctl_internal_t * internal); + +/** + * Call this function to unload one internal client. + * (can be used when the server is running) + * + * @param server server object handle + * @param internal internal to unload + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_unload_internal( + jackctl_server_t * server, + jackctl_internal_t * internal); + +/** + * Call this function to add a slave in the driver slave list. + * (cannot be used when the server is running that is between + * jackctl_server_start and jackctl_server_stop) + * + * @param server server object handle + * @param driver driver to add in the driver slave list. + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_add_slave(jackctl_server_t * server, + jackctl_driver_t * driver); + +/** + * Call this function to remove a slave from the driver slave list. + * (cannot be used when the server is running that is between + * jackctl_server_start and jackctl_server_stop) + * + * @param server server object handle + * @param driver driver to remove from the driver slave list. + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_remove_slave(jackctl_server_t * server, + jackctl_driver_t * driver); + +/** + * Call this function to switch master driver. + * + * @param server server object handle + * @param driver driver to switch to + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_switch_master(jackctl_server_t * server, + jackctl_driver_t * driver); + + +/** + * Call this function to get name of driver. + * + * @param driver driver object handle to get name of + * + * @return driver name. Must not be modified. Always same for same + * driver object. + */ +const char * +jackctl_driver_get_name( + jackctl_driver_t * driver); + +/** + * Call this function to get type of driver. + * + * @param driver driver object handle to get name of + * + * @return driver type. Must not be modified. Always same for same + * driver object. + */ +jackctl_driver_type_t +jackctl_driver_get_type( + jackctl_driver_t * driver); + +/** + * Call this function to get list of driver parameters. List node data + * pointers is a parameter object handle (::jackctl_parameter_t). + * + * @param driver driver object handle to get parameters for + * + * @return Single linked list of parameter object handles. Must not be + * modified. Always same for same driver object. + */ +const JSList * +jackctl_driver_get_parameters( + jackctl_driver_t * driver); + +/** + * Call this function to parse parameters for a driver. + * + * @param driver driver object handle + * @param argc parameter list len + * @param argv parameter list, as an array of char* + * + * @return success status: true - success, false - fail + */ +int +jackctl_driver_params_parse( + jackctl_driver_t * driver, + int argc, + char* argv[]); + +/** + * Call this function to get name of internal client. + * + * @param internal internal object handle to get name of + * + * @return internal name. Must not be modified. Always same for same + * internal object. + */ +const char * +jackctl_internal_get_name( + jackctl_internal_t * internal); + +/** + * Call this function to get list of internal parameters. List node data + * pointers is a parameter object handle (::jackctl_parameter_t). + * + * @param internal internal object handle to get parameters for + * + * @return Single linked list of parameter object handles. Must not be + * modified. Always same for same internal object. + */ +const JSList * +jackctl_internal_get_parameters( + jackctl_internal_t * internal); + +/** + * Call this function to get parameter name. + * + * @param parameter parameter object handle to get name of + * + * @return parameter name. Must not be modified. Always same for same + * parameter object. + */ +const char * +jackctl_parameter_get_name( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter short description. + * + * @param parameter parameter object handle to get short description of + * + * @return parameter short description. Must not be modified. Always + * same for same parameter object. + */ +const char * +jackctl_parameter_get_short_description( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter long description. + * + * @param parameter parameter object handle to get long description of + * + * @return parameter long description. Must not be modified. Always + * same for same parameter object. + */ +const char * +jackctl_parameter_get_long_description( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter type. + * + * @param parameter parameter object handle to get type of + * + * @return parameter type. Always same for same parameter object. + */ +jackctl_param_type_t +jackctl_parameter_get_type( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter character. + * + * @param parameter parameter object handle to get character of + * + * @return character. + */ +char +jackctl_parameter_get_id( + jackctl_parameter_t * parameter); + +/** + * Call this function to check whether parameter has been set, or its + * default value is being used. + * + * @param parameter parameter object handle to check + * + * @return true - parameter is set, false - parameter is using default + * value. + */ +bool +jackctl_parameter_is_set( + jackctl_parameter_t * parameter); + +/** + * Call this function to reset parameter to its default value. + * + * @param parameter parameter object handle to reset value of + * + * @return success status: true - success, false - fail + */ +bool +jackctl_parameter_reset( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter value. + * + * @param parameter parameter object handle to get value of + * + * @return parameter value. + */ +union jackctl_parameter_value +jackctl_parameter_get_value( + jackctl_parameter_t * parameter); + +/** + * Call this function to set parameter value. + * + * @param parameter parameter object handle to get value of + * @param value_ptr pointer to variable containing parameter value + * + * @return success status: true - success, false - fail + */ +bool +jackctl_parameter_set_value( + jackctl_parameter_t * parameter, + const union jackctl_parameter_value * value_ptr); + +/** + * Call this function to get parameter default value. + * + * @param parameter parameter object handle to get default value of + * + * @return parameter default value. + */ +union jackctl_parameter_value +jackctl_parameter_get_default_value( + jackctl_parameter_t * parameter); + +/** + * Call this function check whether parameter has range constraint. + * + * @param parameter object handle of parameter to check + * + * @return whether parameter has range constraint. + */ +bool +jackctl_parameter_has_range_constraint( + jackctl_parameter_t * parameter); + +/** + * Call this function check whether parameter has enumeration constraint. + * + * @param parameter object handle of parameter to check + * + * @return whether parameter has enumeration constraint. + */ +bool +jackctl_parameter_has_enum_constraint( + jackctl_parameter_t * parameter); + +/** + * Call this function get how many enumeration values parameter has. + * + * @param parameter object handle of parameter + * + * @return number of enumeration values + */ +uint32_t +jackctl_parameter_get_enum_constraints_count( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter enumeration value. + * + * @param parameter object handle of parameter + * @param index index of parameter enumeration value + * + * @return enumeration value. + */ +union jackctl_parameter_value +jackctl_parameter_get_enum_constraint_value( + jackctl_parameter_t * parameter, + uint32_t index); + +/** + * Call this function to get parameter enumeration value description. + * + * @param parameter object handle of parameter + * @param index index of parameter enumeration value + * + * @return enumeration value description. + */ +const char * +jackctl_parameter_get_enum_constraint_description( + jackctl_parameter_t * parameter, + uint32_t index); + +/** + * Call this function to get parameter range. + * + * @param parameter object handle of parameter + * @param min_ptr pointer to variable receiving parameter minimum value + * @param max_ptr pointer to variable receiving parameter maximum value + */ +void +jackctl_parameter_get_range_constraint( + jackctl_parameter_t * parameter, + union jackctl_parameter_value * min_ptr, + union jackctl_parameter_value * max_ptr); + +/** + * Call this function to check whether parameter constraint is strict, + * i.e. whether supplying non-matching value will not work for sure. + * + * @param parameter parameter object handle to check + * + * @return whether parameter constraint is strict. + */ +bool +jackctl_parameter_constraint_is_strict( + jackctl_parameter_t * parameter); + +/** + * Call this function to check whether parameter has fake values, + * i.e. values have no user meaningful meaning and only value + * description is meaningful to user. + * + * @param parameter parameter object handle to check + * + * @return whether parameter constraint is strict. + */ +bool +jackctl_parameter_constraint_is_fake_value( + jackctl_parameter_t * parameter); + +/** + * Call this function to log an error message. + * + * @param format string + */ +void +jack_error( + const char *format, + ...); + +/** + * Call this function to log an information message. + * + * @param format string + */ +void +jack_info( + const char *format, + ...); + +/** + * Call this function to log an information message but only when + * verbose mode is enabled. + * + * @param format string + */ +void +jack_log( + const char *format, + ...); + +/* @} */ + +#if 0 +{ /* Adjust editor indent */ +#endif +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* #ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED */ diff --git a/extern/include/jack/intclient.h b/extern/include/jack/intclient.h new file mode 100644 index 00000000..4c126d74 --- /dev/null +++ b/extern/include/jack/intclient.h @@ -0,0 +1,130 @@ +/* +* Copyright (C) 2004 Jack O'Quin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef __jack_intclient_h__ +#define __jack_intclient_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * Get an internal client's name. This is useful when @ref + * JackUseExactName was not specified on jack_internal_client_load() + * and @ref JackNameNotUnique status was returned. In that case, the + * actual name will differ from the @a client_name requested. + * + * @param client requesting JACK client's handle. + * + * @param intclient handle returned from jack_internal_client_load() + * or jack_internal_client_handle(). + * + * @return NULL if unsuccessful, otherwise pointer to the internal + * client name obtained from the heap via malloc(). The caller should + * jack_free() this storage when no longer needed. + */ +char *jack_get_internal_client_name (jack_client_t *client, + jack_intclient_t intclient); + +/** + * Return the @ref jack_intclient_t handle for an internal client + * running in the JACK server. + * + * @param client requesting JACK client's handle. + * + * @param client_name for the internal client of no more than + * jack_client_name_size() characters. The name scope is local to the + * current server. + * + * @param status (if non-NULL) an address for JACK to return + * information from this operation. This status word is formed by + * OR-ing together the relevant @ref JackStatus bits. + * + * @return Opaque internal client handle if successful. If 0, the + * internal client was not found, and @a *status includes the @ref + * JackNoSuchClient and @ref JackFailure bits. + */ +jack_intclient_t jack_internal_client_handle (jack_client_t *client, + const char *client_name, + jack_status_t *status); + +/** + * Load an internal client into the JACK server. + * + * Internal clients run inside the JACK server process. They can use + * most of the same functions as external clients. Each internal + * client is built as a shared object module, which must declare + * jack_initialize() and jack_finish() entry points called at load and + * unload times. See @ref inprocess.c for an example. + * + * @param client loading JACK client's handle. + * + * @param client_name of at most jack_client_name_size() characters + * for the internal client to load. The name scope is local to the + * current server. + * + * @param options formed by OR-ing together @ref JackOptions bits. + * Only the @ref JackLoadOptions bits are valid. + * + * @param status (if non-NULL) an address for JACK to return + * information from the load operation. This status word is formed by + * OR-ing together the relevant @ref JackStatus bits. + * + * Optional parameters: depending on corresponding [@a options + * bits] additional parameters may follow @a status (in this order). + * + * @arg [@ref JackLoadName] (char *) load_name is the shared + * object file from which to load the new internal client (otherwise + * use the @a client_name). + * + * @arg [@ref JackLoadInit] (char *) load_init an arbitary + * string passed to the internal client's jack_initialize() routine + * (otherwise NULL), of no more than @ref JACK_LOAD_INIT_LIMIT bytes. + * + * @return Opaque internal client handle if successful. If this is 0, + * the load operation failed, the internal client was not loaded, and + * @a *status includes the @ref JackFailure bit. + */ +jack_intclient_t jack_internal_client_load (jack_client_t *client, + const char *client_name, + jack_options_t options, + jack_status_t *status, ...); +/** + * Unload an internal client from a JACK server. This calls the + * intclient's jack_finish() entry point then removes it. See @ref + * inprocess.c for an example. + * + * @param client unloading JACK client's handle. + * + * @param intclient handle returned from jack_internal_client_load() or + * jack_internal_client_handle(). + * + * @return 0 if successful, otherwise @ref JackStatus bits. + */ +jack_status_t jack_internal_client_unload (jack_client_t *client, + jack_intclient_t intclient); + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_intclient_h__ */ diff --git a/extern/include/jack/jack.h b/extern/include/jack/jack.h new file mode 100644 index 00000000..bf50e602 --- /dev/null +++ b/extern/include/jack/jack.h @@ -0,0 +1,1470 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004 Jack O'Quin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __jack_h__ +#define __jack_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +/** + * Note: More documentation can be found in jack/types.h. + */ + + /************************************************************* + * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function + * added to the JACK API after the 0.116.2 release. + * + * Functions that predate this release are marked with + * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile + * time in a variety of ways. The default definition is empty, + * so that these symbols get normal linkage. If you wish to + * use all JACK symbols with weak linkage, include + * before jack.h. + *************************************************************/ + +#include + +/** + * Call this function to get version of the JACK, in form of several numbers + * + * @param major_ptr pointer to variable receiving major version of JACK. + * + * @param minor_ptr pointer to variable receiving minor version of JACK. + * + * @param major_ptr pointer to variable receiving micro version of JACK. + * + * @param major_ptr pointer to variable receiving protocol version of JACK. + * + */ +void +jack_get_version( + int *major_ptr, + int *minor_ptr, + int *micro_ptr, + int *proto_ptr) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Call this function to get version of the JACK, in form of a string + * + * @return Human readable string describing JACK version being used. + * + */ +const char * +jack_get_version_string(void) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @defgroup ClientFunctions Creating & manipulating clients + * @{ + */ + +/** + * Open an external client session with a JACK server. This interface + * is more complex but more powerful than jack_client_new(). With it, + * clients may choose which of several servers to connect, and control + * whether and how to start the server automatically, if it was not + * already running. There is also an option for JACK to generate a + * unique client name, when necessary. + * + * @param client_name of at most jack_client_name_size() characters. + * The name scope is local to each server. Unless forbidden by the + * @ref JackUseExactName option, the server will modify this name to + * create a unique variant, if needed. + * + * @param options formed by OR-ing together @ref JackOptions bits. + * Only the @ref JackOpenOptions bits are allowed. + * + * @param status (if non-NULL) an address for JACK to return + * information from the open operation. This status word is formed by + * OR-ing together the relevant @ref JackStatus bits. + * + * + * Optional parameters: depending on corresponding [@a options + * bits] additional parameters may follow @a status (in this order). + * + * @arg [@ref JackServerName] (char *) server_name selects + * from among several possible concurrent server instances. Server + * names are unique to each user. If unspecified, use "default" + * unless \$JACK_DEFAULT_SERVER is defined in the process environment. + * + * @return Opaque client handle if successful. If this is NULL, the + * open operation failed, @a *status includes @ref JackFailure and the + * caller is not a JACK client. + */ +jack_client_t * jack_client_open (const char *client_name, + jack_options_t options, + jack_status_t *status, ...) JACK_OPTIONAL_WEAK_EXPORT; + +/** +* \bold THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN +* NEW JACK CLIENTS +* +* @deprecated Please use jack_client_open(). +*/ +jack_client_t * jack_client_new (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Disconnects an external client from a JACK server. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_client_close (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the maximum number of characters in a JACK client name + * including the final NULL character. This value is a constant. + */ +int jack_client_name_size (void) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return pointer to actual client name. This is useful when @ref + * JackUseExactName is not specified on open and @ref + * JackNameNotUnique status was returned. In that case, the actual + * name will differ from the @a client_name requested. + */ +char * jack_get_client_name (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Get the session ID for a client name. + * + * The session manager needs this to reassociate a client name to the session_id. + * + * The caller is responsible for calling jack_free(3) on any non-NULL + * returned value. + */ +char *jack_get_uuid_for_client_name (jack_client_t *client, + const char *client_name) JACK_WEAK_EXPORT; + +/** + * Get the client name for a session_id. + * + * In order to snapshot the graph connections, the session manager needs to map + * session_ids to client names. + * + * The caller is responsible for calling jack_free(3) on any non-NULL + * returned value. + */ +char *jack_get_client_name_by_uuid (jack_client_t *client, + const char *client_uuid ) JACK_WEAK_EXPORT; + +/** + * Load an internal client into the Jack server. + * + * Internal clients run inside the JACK server process. They can use + * most of the same functions as external clients. Each internal + * client must declare jack_initialize() and jack_finish() entry + * points, called at load and unload times. See inprocess.c for an + * example of how to write an internal client. + * + * @deprecated Please use jack_internal_client_load(). + * + * @param client_name of at most jack_client_name_size() characters. + * + * @param load_name of a shared object file containing the code for + * the new client. + * + * @param load_init an arbitary string passed to the jack_initialize() + * routine of the new client (may be NULL). + * + * @return 0 if successful. + */ +int jack_internal_client_new (const char *client_name, + const char *load_name, + const char *load_init) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Remove an internal client from a JACK server. + * + * @deprecated Please use jack_internal_client_unload(). + */ +void jack_internal_client_close (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Tell the Jack server that the program is ready to start processing + * audio. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_activate (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to remove this @a client from the process + * graph. Also, disconnect all ports belonging to it, since inactive + * clients have no port connections. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_deactivate (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return pid of client. If not available, 0 will be returned. + */ +int jack_get_client_pid (const char *name) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the pthread ID of the thread running the JACK client side + * real-time code. + */ +jack_native_thread_t jack_client_thread_id (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @param client pointer to JACK client structure. + * + * Check if the JACK subsystem is running with -R (--realtime). + * + * @return 1 if JACK is running realtime, 0 otherwise + */ +int jack_is_realtime (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @defgroup NonCallbackAPI The non-callback API + * @{ + */ + +/** + * \bold THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN + * NEW JACK CLIENTS. + * + * @deprecated Please use jack_cycle_wait() and jack_cycle_signal() functions. + */ +jack_nframes_t jack_thread_wait (jack_client_t *client, int status) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Wait until this JACK client should process data. + * + * @param client - pointer to a JACK client structure + * + * @return the number of frames of data to process + */ +jack_nframes_t jack_cycle_wait (jack_client_t* client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Signal next clients in the graph. + * + * @param client - pointer to a JACK client structure + * @param status - if non-zero, calling thread should exit + */ +void jack_cycle_signal (jack_client_t* client, int status) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a thread_callback in the RT thread. + * Typical use are in conjunction with @a jack_cycle_wait and @a jack_cycle_signal functions. + * The code in the supplied function must be suitable for real-time + * execution. That means that it cannot call functions that might + * block for a long time. This includes malloc, free, printf, + * pthread_mutex_lock, sleep, wait, poll, select, pthread_join, + * pthread_cond_wait, etc, etc. See + * http://jackit.sourceforge.net/docs/design/design.html#SECTION00411000000000000000 + * for more information. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code. +*/ +int jack_set_process_thread(jack_client_t* client, JackThreadCallback thread_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup ClientCallbacks Setting Client Callbacks + * @{ + */ + +/** + * Tell JACK to call @a thread_init_callback once just after + * the creation of the thread in which all other callbacks + * will be handled. + * + * The code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code, causing JACK + * to remove that client from the process() graph. + */ +int jack_set_thread_init_callback (jack_client_t *client, + JackThreadInitCallback thread_init_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @param client pointer to JACK client structure. + * @param function The jack_shutdown function pointer. + * @param arg The arguments for the jack_shutdown function. + * + * Register a function (and argument) to be called if and when the + * JACK server shuts down the client thread. The function must + * be written as if it were an asynchonrous POSIX signal + * handler --- use only async-safe functions, and remember that it + * is executed from another thread. A typical function might + * set a flag or write to a pipe so that the rest of the + * application knows that the JACK client thread has shut + * down. + * + * NOTE: clients do not need to call this. It exists only + * to help more complex clients understand what is going + * on. It should be called before jack_client_activate(). + * + * NOTE: if a client calls this AND jack_on_info_shutdown(), then + * in case of a client thread shutdown, the callback + * passed to this function will not be called, and the one passed to + * jack_on_info_shutdown() will. + * + * NOTE: application should typically signal another thread to correctly + * finish cleanup, that is by calling "jack_client_close" + * (since "jack_client_close" cannot be called directly in the context + * of the thread that calls the shutdown callback). + */ +void jack_on_shutdown (jack_client_t *client, + JackShutdownCallback shutdown_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @param client pointer to JACK client structure. + * @param function The jack_info_shutdown function pointer. + * @param arg The arguments for the jack_info_shutdown function. + * + * Register a function (and argument) to be called if and when the + * JACK server shuts down the client thread. The function must + * be written as if it were an asynchonrous POSIX signal + * handler --- use only async-safe functions, and remember that it + * is executed from another thread. A typical function might + * set a flag or write to a pipe so that the rest of the + * application knows that the JACK client thread has shut + * down. + * + * NOTE: clients do not need to call this. It exists only + * to help more complex clients understand what is going + * on. It should be called before jack_client_activate(). + * + * NOTE: if a client calls this AND jack_on_shutdown(), then + * in case of a client thread shutdown, the callback passed to + * jack_on_info_shutdown() will be called. + * + * NOTE: application should typically signal another thread to correctly + * finish cleanup, that is by calling "jack_client_close" + * (since "jack_client_close" cannot be called directly in the context + * of the thread that calls the shutdown callback). + */ +void jack_on_info_shutdown (jack_client_t *client, + JackInfoShutdownCallback shutdown_callback, void *arg) JACK_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a process_callback whenever there is + * work be done, passing @a arg as the second argument. + * + * The code in the supplied function must be suitable for real-time + * execution. That means that it cannot call functions that might + * block for a long time. This includes malloc, free, printf, + * pthread_mutex_lock, sleep, wait, poll, select, pthread_join, + * pthread_cond_wait, etc, etc. See + * http://jackit.sourceforge.net/docs/design/design.html#SECTION00411000000000000000 + * for more information. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_process_callback (jack_client_t *client, + JackProcessCallback process_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a freewheel_callback + * whenever we enter or leave "freewheel" mode, passing @a + * arg as the second argument. The first argument to the + * callback will be non-zero if JACK is entering freewheel + * mode, and zero otherwise. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_freewheel_callback (jack_client_t *client, + JackFreewheelCallback freewheel_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell JACK to call @a bufsize_callback whenever the size of the the + * buffer that will be passed to the @a process_callback is about to + * change. Clients that depend on knowing the buffer size must supply + * a @a bufsize_callback before activating themselves. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @param client pointer to JACK client structure. + * @param bufsize_callback function to call when the buffer size changes. + * @param arg argument for @a bufsize_callback. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_buffer_size_callback (jack_client_t *client, + JackBufferSizeCallback bufsize_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a srate_callback whenever the system + * sample rate changes. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_sample_rate_callback (jack_client_t *client, + JackSampleRateCallback srate_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a client_registration_callback whenever a + * client is registered or unregistered, passing @a arg as a parameter. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_client_registration_callback (jack_client_t *client, + JackClientRegistrationCallback + registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a registration_callback whenever a + * port is registered or unregistered, passing @a arg as a parameter. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code + */ + int jack_set_port_registration_callback (jack_client_t *client, + JackPortRegistrationCallback + registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + + /** + * Tell the JACK server to call @a connect_callback whenever a + * port is connected or disconnected, passing @a arg as a parameter. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_port_connect_callback (jack_client_t *client, + JackPortConnectCallback + connect_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + + /** + * Tell the JACK server to call @a rename_callback whenever a + * port is renamed, passing @a arg as a parameter. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_port_rename_callback (jack_client_t *client, + JackPortRenameCallback + rename_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a graph_callback whenever the + * processing graph is reordered, passing @a arg as a parameter. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_graph_order_callback (jack_client_t *client, + JackGraphOrderCallback graph_callback, + void *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a xrun_callback whenever there is a + * xrun, passing @a arg as a parameter. + * + * All "notification events" are received in a seperated non RT thread, + * the code in the supplied function does not need to be + * suitable for real-time execution. + * + * NOTE: this function cannot be called while the client is activated + * (after jack_activate has been called.) + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_xrun_callback (jack_client_t *client, + JackXRunCallback xrun_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * Tell the Jack server to call @a latency_callback whenever it + * is necessary to recompute the latencies for some or all + * Jack ports. + * + * @a latency_callback will be called twice each time it is + * needed, once being passed JackCaptureLatency and once + * JackPlaybackLatency. See @ref LatencyFunctions for + * the definition of each type of latency and related functions. + * + * IMPORTANT: Most JACK clients do NOT need to register a latency + * callback. + * + * Clients that meet any of the following conditions do NOT + * need to register a latency callback: + * + * - have only input ports + * - have only output ports + * - their output is totally unrelated to their input + * - their output is not delayed relative to their input + * (i.e. data that arrives in a given process() + * callback is processed and output again in the + * same callback) + * + * Clients NOT registering a latency callback MUST also + * satisfy this condition: + * + * - have no multiple distinct internal signal pathways + * + * This means that if your client has more than 1 input and + * output port, and considers them always "correlated" + * (e.g. as a stereo pair), then there is only 1 (e.g. stereo) + * signal pathway through the client. This would be true, + * for example, of a stereo FX rack client that has a + * left/right input pair and a left/right output pair. + * + * However, this is somewhat a matter of perspective. The + * same FX rack client could be connected so that its + * two input ports were connected to entirely separate + * sources. Under these conditions, the fact that the client + * does not register a latency callback MAY result + * in port latency values being incorrect. + * + * Clients that do not meet any of those conditions SHOULD + * register a latency callback. + * + * See the documentation for @ref jack_port_set_latency_range() + * on how the callback should operate. Remember that the @a mode + * argument given to the latency callback will need to be + * passed into @ref jack_port_set_latency_range() + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_latency_callback (jack_client_t *client, + JackLatencyCallback latency_callback, + void *) JACK_WEAK_EXPORT; +/*@}*/ + +/** + * @defgroup ServerClientControl Controlling & querying JACK server operation + * @{ + */ + +/** + * Start/Stop JACK's "freewheel" mode. + * + * When in "freewheel" mode, JACK no longer waits for + * any external event to begin the start of the next process + * cycle. + * + * As a result, freewheel mode causes "faster than realtime" + * execution of a JACK graph. If possessed, real-time + * scheduling is dropped when entering freewheel mode, and + * if appropriate it is reacquired when stopping. + * + * IMPORTANT: on systems using capabilities to provide real-time + * scheduling (i.e. Linux kernel 2.4), if onoff is zero, this function + * must be called from the thread that originally called jack_activate(). + * This restriction does not apply to other systems (e.g. Linux kernel 2.6 + * or OS X). + * + * @param client pointer to JACK client structure + * @param onoff if non-zero, freewheel mode starts. Otherwise + * freewheel mode ends. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_freewheel(jack_client_t* client, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Change the buffer size passed to the @a process_callback. + * + * This operation stops the JACK engine process cycle, then calls all + * registered @a bufsize_callback functions before restarting the + * process cycle. This will cause a gap in the audio flow, so it + * should only be done at appropriate stopping points. + * + * @see jack_set_buffer_size_callback() + * + * @param client pointer to JACK client structure. + * @param nframes new buffer size. Must be a power of two. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the sample rate of the jack system, as set by the user when + * jackd was started. + */ +jack_nframes_t jack_get_sample_rate (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the current maximum size that will ever be passed to the @a + * process_callback. It should only be used *before* the client has + * been activated. This size may change, clients that depend on it + * must register a @a bufsize_callback so they will be notified if it + * does. + * + * @see jack_set_buffer_size_callback() + */ +jack_nframes_t jack_get_buffer_size (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Old-style interface to become the timebase for the entire JACK + * subsystem. + * + * @deprecated This function still exists for compatibility with the + * earlier transport interface, but it does nothing. Instead, see + * transport.h and use jack_set_timebase_callback(). + * + * @return ENOSYS, function not implemented. + */ +int jack_engine_takeover_timebase (jack_client_t *) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * @return the current CPU load estimated by JACK. This is a running + * average of the time it takes to execute a full process cycle for + * all clients as a percentage of the real time available per cycle + * determined by the buffer size and sample rate. + */ +float jack_cpu_load (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup PortFunctions Creating & manipulating ports + * @{ + */ + +/** + * Create a new port for the client. This is an object used for moving + * data of any type in or out of the client. Ports may be connected + * in various ways. + * + * Each port has a short name. The port's full name contains the name + * of the client concatenated with a colon (:) followed by its short + * name. The jack_port_name_size() is the maximum length of this full + * name. Exceeding that will cause the port registration to fail and + * return NULL. + * + * The @a port_name must be unique among all ports owned by this client. + * If the name is not unique, the registration will fail. + * + * All ports have a type, which may be any non-NULL and non-zero + * length string, passed as an argument. Some port types are built + * into the JACK API, currently only JACK_DEFAULT_AUDIO_TYPE. + * + * @param client pointer to JACK client structure. + * @param port_name non-empty short name for the new port (not + * including the leading @a "client_name:"). Must be unique. + * @param port_type port type name. If longer than + * jack_port_type_size(), only that many characters are significant. + * @param flags @ref JackPortFlags bit mask. + * @param buffer_size must be non-zero if this is not a built-in @a + * port_type. Otherwise, it is ignored. + * + * @return jack_port_t pointer on success, otherwise NULL. + */ +jack_port_t * jack_port_register (jack_client_t *client, + const char *port_name, + const char *port_type, + unsigned long flags, + unsigned long buffer_size) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Remove the port from the client, disconnecting any existing + * connections. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_unregister (jack_client_t *client, jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * This returns a pointer to the memory area associated with the + * specified port. For an output port, it will be a memory area + * that can be written to; for an input port, it will be an area + * containing the data from the port's connection(s), or + * zero-filled. if there are multiple inbound connections, the data + * will be mixed appropriately. + * + * FOR OUTPUT PORTS ONLY : DEPRECATED in Jack 2.0 !! + * --------------------------------------------------- + * You may cache the value returned, but only between calls to + * your "blocksize" callback. For this reason alone, you should + * either never cache the return value or ensure you have + * a "blocksize" callback and be sure to invalidate the cached + * address from there. + * + * Caching output ports is DEPRECATED in Jack 2.0, due to some new optimization (like "pipelining"). + * Port buffers have to be retrieved in each callback for proper functionning. + */ +void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the UUID of the jack_port_t + * + * @see jack_uuid_to_string() to convert into a string representation + */ +jack_uuid_t jack_port_uuid (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the full name of the jack_port_t (including the @a + * "client_name:" prefix). + * + * @see jack_port_name_size(). + */ +const char * jack_port_name (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the short name of the jack_port_t (not including the @a + * "client_name:" prefix). + * + * @see jack_port_name_size(). + */ +const char * jack_port_short_name (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the @ref JackPortFlags of the jack_port_t. + */ +int jack_port_flags (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the @a port type, at most jack_port_type_size() characters + * including a final NULL. + */ +const char * jack_port_type (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + + /** + * @return the @a port type id. + */ +jack_port_type_id_t jack_port_type_id (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return TRUE if the jack_port_t belongs to the jack_client_t. + */ +int jack_port_is_mine (const jack_client_t *client, const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return number of connections to or from @a port. + * + * @pre The calling client must own @a port. + */ +int jack_port_connected (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return TRUE if the locally-owned @a port is @b directly connected + * to the @a port_name. + * + * @see jack_port_name_size() + */ +int jack_port_connected_to (const jack_port_t *port, + const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return a null-terminated array of full port names to which the @a + * port is connected. If none, returns NULL. + * + * The caller is responsible for calling jack_free() on any non-NULL + * returned value. + * + * @param port locally owned jack_port_t pointer. + * + * @see jack_port_name_size(), jack_port_get_all_connections() + */ +const char ** jack_port_get_connections (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return a null-terminated array of full port names to which the @a + * port is connected. If none, returns NULL. + * + * The caller is responsible for calling jack_free() on any non-NULL + * returned value. + * + * This differs from jack_port_get_connections() in two important + * respects: + * + * 1) You may not call this function from code that is + * executed in response to a JACK event. For example, + * you cannot use it in a GraphReordered handler. + * + * 2) You need not be the owner of the port to get information + * about its connections. + * + * @see jack_port_name_size() + */ +const char ** jack_port_get_all_connections (const jack_client_t *client, + const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * + * @deprecated This function will be removed from a future version + * of JACK. Do not use it. There is no replacement. It has + * turned out to serve essentially no purpose in real-life + * JACK clients. + */ +int jack_port_tie (jack_port_t *src, jack_port_t *dst) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * + * @deprecated This function will be removed from a future version + * of JACK. Do not use it. There is no replacement. It has + * turned out to serve essentially no purpose in real-life + * JACK clients. + */ +int jack_port_untie (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * \bold THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN + * NEW JACK CLIENTS + * + * Modify a port's short name. May be called at any time. If the + * resulting full name (including the @a "client_name:" prefix) is + * longer than jack_port_name_size(), it will be truncated. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_port_set_name (jack_port_t *port, const char *port_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Modify a port's short name. May NOT be called from a callback handling a server event. + * If the resulting full name (including the @a "client_name:" prefix) is + * longer than jack_port_name_size(), it will be truncated. + * + * @return 0 on success, otherwise a non-zero error code. + * + * This differs from jack_port_set_name() by triggering PortRename notifications to + * clients that have registered a port rename handler. + */ +int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set @a alias as an alias for @a port. May be called at any time. + * If the alias is longer than jack_port_name_size(), it will be truncated. + * + * After a successful call, and until JACK exits or + * @function jack_port_unset_alias() is called, @alias may be + * used as a alternate name for the port. + * + * Ports can have up to two aliases - if both are already + * set, this function will return an error. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_port_set_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Remove @a alias as an alias for @a port. May be called at any time. + * + * After a successful call, @a alias can no longer be + * used as a alternate name for the port. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_port_unset_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Get any aliases known for @port. + * + * @return the number of aliases discovered for the port + */ +int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2]) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * If @ref JackPortCanMonitor is set for this @a port, turn input + * monitoring on or off. Otherwise, do nothing. + */ +int jack_port_request_monitor (jack_port_t *port, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * If @ref JackPortCanMonitor is set for this @a port_name, turn input + * monitoring on or off. Otherwise, do nothing. + * + * @return 0 on success, otherwise a non-zero error code. + * + * @see jack_port_name_size() + */ +int jack_port_request_monitor_by_name (jack_client_t *client, + const char *port_name, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * If @ref JackPortCanMonitor is set for a port, this function turns + * on input monitoring if it was off, and turns it off if only one + * request has been made to turn it on. Otherwise it does nothing. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_ensure_monitor (jack_port_t *port, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return TRUE if input monitoring has been requested for @a port. + */ +int jack_port_monitoring_input (jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Establish a connection between two ports. + * + * When a connection exists, data written to the source port will + * be available to be read at the destination port. + * + * @pre The port types must be identical. + * + * @pre The @ref JackPortFlags of the @a source_port must include @ref + * JackPortIsOutput. + * + * @pre The @ref JackPortFlags of the @a destination_port must include + * @ref JackPortIsInput. + * + * @return 0 on success, EEXIST if the connection is already made, + * otherwise a non-zero error code + */ +int jack_connect (jack_client_t *client, + const char *source_port, + const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Remove a connection between two ports. + * + * @pre The port types must be identical. + * + * @pre The @ref JackPortFlags of the @a source_port must include @ref + * JackPortIsOutput. + * + * @pre The @ref JackPortFlags of the @a destination_port must include + * @ref JackPortIsInput. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_disconnect (jack_client_t *client, + const char *source_port, + const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Perform the same function as jack_disconnect() using port handles + * rather than names. This avoids the name lookup inherent in the + * name-based version. + * + * Clients connecting their own ports are likely to use this function, + * while generic connection clients (e.g. patchbays) would use + * jack_disconnect(). + */ +int jack_port_disconnect (jack_client_t *client, jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the maximum number of characters in a full JACK port name + * including the final NULL character. This value is a constant. + * + * A port's full name contains the owning client name concatenated + * with a colon (:) followed by its short name and a NULL + * character. + */ +int jack_port_name_size(void) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the maximum number of characters in a JACK port type name + * including the final NULL character. This value is a constant. + */ +int jack_port_type_size(void) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the buffersize of a port of type @arg port_type. + * + * this function may only be called in a buffer_size callback. + */ +size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_type) JACK_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup LatencyFunctions Managing and determining latency + * + * The purpose of JACK's latency API is to allow clients to + * easily answer two questions: + * + * - How long has it been since the data read from a port arrived + * at the edge of the JACK graph (either via a physical port + * or being synthesized from scratch)? + * + * - How long will it be before the data written to a port arrives + * at the edge of a JACK graph? + + * To help answering these two questions, all JACK ports have two + * latency values associated with them, both measured in frames: + * + * capture latency: how long since the data read from + * the buffer of a port arrived at + * a port marked with JackPortIsTerminal. + * The data will have come from the "outside + * world" if the terminal port is also + * marked with JackPortIsPhysical, or + * will have been synthesized by the client + * that owns the terminal port. + * + * playback latency: how long until the data + * written to the buffer of port will reach a port + * marked with JackPortIsTerminal. + * + * Both latencies might potentially have more than one value + * because there may be multiple pathways to/from a given port + * and a terminal port. Latency is therefore generally + * expressed a min/max pair. + * + * In most common setups, the minimum and maximum latency + * are the same, but this design accomodates more complex + * routing, and allows applications (and thus users) to + * detect cases where routing is creating an anomalous + * situation that may either need fixing or more + * sophisticated handling by clients that care about + * latency. + * + * See also @ref jack_set_latency_callback for details on how + * clients that add latency to the signal path should interact + * with JACK to ensure that the correct latency figures are + * used. + * @{ + */ + +/** + * The port latency is zero by default. Clients that control + * physical hardware with non-zero latency should call this + * to set the latency to its correct value. Note that the value + * should include any systemic latency present "outside" the + * physical hardware controlled by the client. For example, + * for a client controlling a digital audio interface connected + * to an external digital converter, the latency setting should + * include both buffering by the audio interface *and* the converter. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by a latency callback that calls @ref + * jack_port_set_latency_range(). + */ +void jack_port_set_latency (jack_port_t *port, jack_nframes_t) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * return the latency range defined by @a mode for + * @a port, in frames. + * + * See @ref LatencyFunctions for the definition of each latency value. + * + * This is normally used in the LatencyCallback. + * and therefor safe to execute from callbacks. + */ +void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; + +/** + * set the minimum and maximum latencies defined by + * @a mode for @a port, in frames. + * + * See @ref LatencyFunctions for the definition of each latency value. + * + * This function should ONLY be used inside a latency + * callback. The client should determine the current + * value of the latency using @ref jack_port_get_latency_range() + * (called using the same mode as @a mode) + * and then add some number of frames to that reflects + * latency added by the client. + * + * How much latency a client adds will vary + * dramatically. For most clients, the answer is zero + * and there is no reason for them to register a latency + * callback and thus they should never call this + * function. + * + * More complex clients that take an input signal, + * transform it in some way and output the result but + * not during the same process() callback will + * generally know a single constant value to add + * to the value returned by @ref jack_port_get_latency_range(). + * + * Such clients would register a latency callback (see + * @ref jack_set_latency_callback) and must know what input + * ports feed which output ports as part of their + * internal state. Their latency callback will update + * the ports' latency values appropriately. + * + * A pseudo-code example will help. The @a mode argument to the latency + * callback will determine whether playback or capture + * latency is being set. The callback will use + * @ref jack_port_set_latency_range() as follows: + * + * \code + * jack_latency_range_t range; + * if (mode == JackPlaybackLatency) { + * foreach input_port in (all self-registered port) { + * jack_port_get_latency_range (port_feeding_input_port, JackPlaybackLatency, &range); + * range.min += min_delay_added_as_signal_flows_from port_feeding to input_port; + * range.max += max_delay_added_as_signal_flows_from port_feeding to input_port; + * jack_port_set_latency_range (input_port, JackPlaybackLatency, &range); + * } + * } else if (mode == JackCaptureLatency) { + * foreach output_port in (all self-registered port) { + * jack_port_get_latency_range (port_fed_by_output_port, JackCaptureLatency, &range); + * range.min += min_delay_added_as_signal_flows_from_output_port_to_fed_by_port; + * range.max += max_delay_added_as_signal_flows_from_output_port_to_fed_by_port; + * jack_port_set_latency_range (output_port, JackCaptureLatency, &range); + * } + * } + * \endcode + * + * In this relatively simple pseudo-code example, it is assumed that + * each input port or output is connected to only 1 output or input + * port respectively. + * + * If a port is connected to more than 1 other port, then the + * range.min and range.max values passed to @ref + * jack_port_set_latency_range() should reflect the minimum and + * maximum values across all connected ports. + * + * See the description of @ref jack_set_latency_callback for more + * information. + */ +void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; + +/** + * Request a complete recomputation of all port latencies. This + * can be called by a client that has just changed the internal + * latency of its port using jack_port_set_latency + * and wants to ensure that all signal pathways in the graph + * are updated with respect to the values that will be returned + * by jack_port_get_total_latency. It allows a client + * to change multiple port latencies without triggering a + * recompute for each change. + * + * @return zero for successful execution of the request. non-zero + * otherwise. + */ +int jack_recompute_total_latencies (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the time (in frames) between data being available or + * delivered at/to a port, and the time at which it arrived at or is + * delivered to the "other side" of the port. E.g. for a physical + * audio output port, this is the time between writing to the port and + * when the signal will leave the connector. For a physical audio + * input port, this is the time between the sound arriving at the + * connector and the corresponding frames being readable from the + * port. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_port_get_latency_range() in any existing + * use cases. + */ +jack_nframes_t jack_port_get_latency (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * The maximum of the sum of the latencies in every + * connection path that can be drawn between the port and other + * ports with the @ref JackPortIsTerminal flag set. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_port_get_latency_range() in any existing + * use cases. + */ +jack_nframes_t jack_port_get_total_latency (jack_client_t *client, + jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Request a complete recomputation of a port's total latency. This + * can be called by a client that has just changed the internal + * latency of its port using jack_port_set_latency + * and wants to ensure that all signal pathways in the graph + * are updated with respect to the values that will be returned + * by jack_port_get_total_latency. + * + * @return zero for successful execution of the request. non-zero + * otherwise. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_recompute_total_latencies() in any existing + * use cases. + */ +int jack_recompute_total_latency (jack_client_t*, jack_port_t* port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/*@}*/ + +/** + * @defgroup PortSearching Looking up ports + * @{ + */ + +/** + * @param port_name_pattern A regular expression used to select + * ports by name. If NULL or of zero length, no selection based + * on name will be carried out. + * @param type_name_pattern A regular expression used to select + * ports by type. If NULL or of zero length, no selection based + * on type will be carried out. + * @param flags A value used to select ports by their flags. + * If zero, no selection based on flags will be carried out. + * + * @return a NULL-terminated array of ports that match the specified + * arguments. The caller is responsible for calling jack_free() any + * non-NULL returned value. + * + * @see jack_port_name_size(), jack_port_type_size() + */ +const char ** jack_get_ports (jack_client_t *client, + const char *port_name_pattern, + const char *type_name_pattern, + unsigned long flags) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return address of the jack_port_t named @a port_name. + * + * @see jack_port_name_size() + */ +jack_port_t * jack_port_by_name (jack_client_t *client, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return address of the jack_port_t of a @a port_id. + */ +jack_port_t * jack_port_by_id (jack_client_t *client, + jack_port_id_t port_id) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup TimeFunctions Handling time + * @{ + * + * JACK time is in units of 'frames', according to the current sample rate. + * The absolute value of frame times is meaningless, frame times have meaning + * only relative to each other. + */ + +/** + * @return the estimated time in frames that has passed since the JACK + * server began the current process cycle. + */ +jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the estimated current time in frames. + * This function is intended for use in other threads (not the process + * callback). The return value can be compared with the value of + * jack_last_frame_time to relate time in other threads to JACK time. + */ +jack_nframes_t jack_frame_time (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the precise time at the start of the current process cycle. + * This function may only be used from the process callback, and can + * be used to interpret timestamps generated by jack_frame_time() in + * other threads with respect to the current process cycle. + * + * This is the only jack time function that returns exact time: + * when used during the process callback it always returns the same + * value (until the next process callback, where it will return + * that value + nframes, etc). The return value is guaranteed to be + * monotonic and linear in this fashion unless an xrun occurs. + * If an xrun occurs, clients must check this value again, as time + * may have advanced in a non-linear way (e.g. cycles may have been skipped). + */ +jack_nframes_t jack_last_frame_time (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * This function may only be used from the process callback. + * It provides the internal cycle timing information as used by + * most of the other time related functions. This allows the + * caller to map between frame counts and microseconds with full + * precision (i.e. without rounding frame times to integers), + * and also provides e.g. the microseconds time of the start of + * the current cycle directly (it has to be computed otherwise). + * + * If the return value is zero, the following information is + * provided in the variables pointed to by the arguments: + * + * current_frames: the frame time counter at the start of the + * current cycle, same as jack_last_frame_time(). + * current_usecs: the microseconds time at the start of the + * current cycle. + * next_usecs: the microseconds time of the start of the next + * next cycle as computed by the DLL. + * period_usecs: the current best estimate of the period time in + * microseconds. + * + * NOTES: + * + * Because of the types used, all the returned values except period_usecs + * are unsigned. In computations mapping between frames and microseconds + * *signed* differences are required. The easiest way is to compute those + * separately and assign them to the appropriate signed variables, + * int32_t for frames and int64_t for usecs. See the implementation of + * jack_frames_to_time() and Jack_time_to_frames() for an example. + * + * Unless there was an xrun, skipped cycles, or the current cycle is the + * first after freewheeling or starting Jack, the value of current_usecs + * will always be the value of next_usecs of the previous cycle. + * + * The value of period_usecs will in general NOT be exactly equal to + * the difference of next_usecs and current_usecs. This is because to + * ensure stability of the DLL and continuity of the mapping, a fraction + * of the loop error must be included in next_usecs. For an accurate + * mapping between frames and microseconds, the difference of next_usecs + * and current_usecs should be used, and not period_usecs. + * + * @return zero if OK, non-zero otherwise. + */ +int jack_get_cycle_times(const jack_client_t *client, + jack_nframes_t *current_frames, + jack_time_t *current_usecs, + jack_time_t *next_usecs, + float *period_usecs) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the estimated time in microseconds of the specified frame time + */ +jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the estimated time in frames for the specified system time. + */ +jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return return JACK's current system time in microseconds, + * using the JACK clock source. + * + * The value returned is guaranteed to be monotonic, but not linear. + */ +jack_time_t jack_get_time(void) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup ErrorOutput Controlling error/information output + */ +/*@{*/ + +/** + * Display JACK error message. + * + * Set via jack_set_error_function(), otherwise a JACK-provided + * default will print @a msg (plus a newline) to stderr. + * + * @param msg error message text (no newline at end). + */ +extern void (*jack_error_callback)(const char *msg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set the @ref jack_error_callback for error message display. + * Set it to NULL to restore default_jack_error_callback function. + * + * The JACK library provides two built-in callbacks for this purpose: + * default_jack_error_callback() and silent_jack_error_callback(). + */ +void jack_set_error_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Display JACK info message. + * + * Set via jack_set_info_function(), otherwise a JACK-provided + * default will print @a msg (plus a newline) to stdout. + * + * @param msg info message text (no newline at end). + */ +extern void (*jack_info_callback)(const char *msg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set the @ref jack_info_callback for info message display. + * Set it to NULL to restore default_jack_info_callback function. + * + * The JACK library provides two built-in callbacks for this purpose: + * default_jack_info_callback() and silent_jack_info_callback(). + */ +void jack_set_info_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * The free function to be used on memory returned by jack_port_get_connections, + * jack_port_get_all_connections, jack_get_ports and jack_get_internal_client_name functions. + * This is MANDATORY on Windows when otherwise all nasty runtime version related crashes can occur. + * Developers are strongly encouraged to use this function instead of the standard "free" function in new code. + * + * @param ptr the memory pointer to be deallocated. + */ +void jack_free(void* ptr) JACK_OPTIONAL_WEAK_EXPORT; + + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_h__ */ diff --git a/extern/include/jack/jslist.h b/extern/include/jack/jslist.h new file mode 100644 index 00000000..3ec0ce92 --- /dev/null +++ b/extern/include/jack/jslist.h @@ -0,0 +1,293 @@ +/* + Based on gslist.c from glib-1.2.9 (LGPL). + + Adaption to JACK, Copyright (C) 2002 Kai Vehmanen. + - replaced use of gtypes with normal ANSI C types + - glib's memory allocation routines replaced with + malloc/free calls + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __jack_jslist_h__ +#define __jack_jslist_h__ + +#include +#include + +#ifdef sun +#define __inline__ +#endif + +typedef struct _JSList JSList; + +typedef int (*JCompareFunc) (void* a, void* b); +struct _JSList +{ + void *data; + JSList *next; +}; + +static __inline__ +JSList* +jack_slist_alloc (void) +{ + JSList *new_list; + + new_list = (JSList*)malloc(sizeof(JSList)); + if (new_list) { + new_list->data = NULL; + new_list->next = NULL; + } + + return new_list; +} + +static __inline__ +JSList* +jack_slist_prepend (JSList* list, void* data) +{ + JSList *new_list; + + new_list = (JSList*)malloc(sizeof(JSList)); + if (new_list) { + new_list->data = data; + new_list->next = list; + } + + return new_list; +} + +#define jack_slist_next(slist) ((slist) ? (((JSList *)(slist))->next) : NULL) +static __inline__ +JSList* +jack_slist_last (JSList *list) +{ + if (list) { + while (list->next) + list = list->next; + } + + return list; +} + +static __inline__ +JSList* +jack_slist_remove_link (JSList *list, + JSList *link) +{ + JSList *tmp; + JSList *prev; + + prev = NULL; + tmp = list; + + while (tmp) { + if (tmp == link) { + if (prev) + prev->next = tmp->next; + if (list == tmp) + list = list->next; + + tmp->next = NULL; + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +static __inline__ +void +jack_slist_free (JSList *list) +{ + while (list) { + JSList *next = list->next; + free(list); + list = next; + } +} + +static __inline__ +void +jack_slist_free_1 (JSList *list) +{ + if (list) { + free(list); + } +} + +static __inline__ +JSList* +jack_slist_remove (JSList *list, + void *data) +{ + JSList *tmp; + JSList *prev; + + prev = NULL; + tmp = list; + + while (tmp) { + if (tmp->data == data) { + if (prev) + prev->next = tmp->next; + if (list == tmp) + list = list->next; + + tmp->next = NULL; + jack_slist_free (tmp); + + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +static __inline__ +unsigned int +jack_slist_length (JSList *list) +{ + unsigned int length; + + length = 0; + while (list) { + length++; + list = list->next; + } + + return length; +} + +static __inline__ +JSList* +jack_slist_find (JSList *list, + void *data) +{ + while (list) { + if (list->data == data) + break; + list = list->next; + } + + return list; +} + +static __inline__ +JSList* +jack_slist_copy (JSList *list) +{ + JSList *new_list = NULL; + + if (list) { + JSList *last; + + new_list = jack_slist_alloc (); + new_list->data = list->data; + last = new_list; + list = list->next; + while (list) { + last->next = jack_slist_alloc (); + last = last->next; + last->data = list->data; + list = list->next; + } + } + + return new_list; +} + +static __inline__ +JSList* +jack_slist_append (JSList *list, + void *data) +{ + JSList *new_list; + JSList *last; + + new_list = jack_slist_alloc (); + new_list->data = data; + + if (list) { + last = jack_slist_last (list); + last->next = new_list; + + return list; + } else + return new_list; +} + +static __inline__ +JSList* +jack_slist_sort_merge (JSList *l1, + JSList *l2, + JCompareFunc compare_func) +{ + JSList list, *l; + + l = &list; + + while (l1 && l2) { + if (compare_func(l1->data, l2->data) < 0) { + l = l->next = l1; + l1 = l1->next; + } else { + l = l->next = l2; + l2 = l2->next; + } + } + l->next = l1 ? l1 : l2; + + return list.next; +} + +static __inline__ +JSList* +jack_slist_sort (JSList *list, + JCompareFunc compare_func) +{ + JSList *l1, *l2; + + if (!list) + return NULL; + if (!list->next) + return list; + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) { + if ((l2 = l2->next) == NULL) + break; + l1 = l1->next; + } + l2 = l1->next; + l1->next = NULL; + + return jack_slist_sort_merge (jack_slist_sort (list, compare_func), + jack_slist_sort (l2, compare_func), + compare_func); +} + +#endif /* __jack_jslist_h__ */ + diff --git a/extern/include/jack/midiport.h b/extern/include/jack/midiport.h new file mode 100644 index 00000000..1a7d4e6d --- /dev/null +++ b/extern/include/jack/midiport.h @@ -0,0 +1,184 @@ +/* + Copyright (C) 2004 Ian Esten + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + + +#ifndef __JACK_MIDIPORT_H +#define __JACK_MIDIPORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + +/** Type for raw event data contained in @ref jack_midi_event_t. */ +typedef unsigned char jack_midi_data_t; + + +/** A Jack MIDI event. */ +typedef struct _jack_midi_event +{ + jack_nframes_t time; /**< Sample index at which event is valid */ + size_t size; /**< Number of bytes of data in \a buffer */ + jack_midi_data_t *buffer; /**< Raw MIDI data */ +} jack_midi_event_t; + + +/** + * @defgroup MIDIAPI Reading and writing MIDI data + * @{ + */ + +/** Get number of events in a port buffer. + * + * @param port_buffer Port buffer from which to retrieve event. + * @return number of events inside @a port_buffer + */ +uint32_t +jack_midi_get_event_count(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Get a MIDI event from an event port buffer. + * + * Jack MIDI is normalised, the MIDI event returned by this function is + * guaranteed to be a complete MIDI event (the status byte will always be + * present, and no realtime events will interspered with the event). + * + * @param event Event structure to store retrieved event in. + * @param port_buffer Port buffer from which to retrieve event. + * @param event_index Index of event to retrieve. + * @return 0 on success, ENODATA if buffer is empty. + */ +int +jack_midi_event_get(jack_midi_event_t *event, + void *port_buffer, + uint32_t event_index) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Clear an event buffer. + * + * This should be called at the beginning of each process cycle before calling + * @ref jack_midi_event_reserve or @ref jack_midi_event_write. This + * function may not be called on an input port's buffer. + * + * @param port_buffer Port buffer to clear (must be an output port buffer). + */ +void +jack_midi_clear_buffer(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + +/** Reset an event buffer (from data allocated outside of JACK). + * + * This should be called at the beginning of each process cycle before calling + * @ref jack_midi_event_reserve or @ref jack_midi_event_write. This + * function may not be called on an input port's buffer. + * + * @param port_buffer Port buffer to resetted. + */ +void +jack_midi_reset_buffer(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Get the size of the largest event that can be stored by the port. + * + * This function returns the current space available, taking into account + * events already stored in the port. + * + * @param port_buffer Port buffer to check size of. + */ +size_t +jack_midi_max_event_size(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Allocate space for an event to be written to an event port buffer. + * + * Clients are to write the actual event data to be written starting at the + * pointer returned by this function. Clients must not write more than + * @a data_size bytes into this buffer. Clients must write normalised + * MIDI data to the port - no running status and no (1-byte) realtime + * messages interspersed with other messages (realtime messages are fine + * when they occur on their own, like other messages). + * + * Events must be written in order, sorted by their sample offsets. + * JACK will not sort the events for you, and will refuse to store + * out-of-order events. + * + * @param port_buffer Buffer to write event to. + * @param time Sample offset of event. + * @param data_size Length of event's raw data in bytes. + * @return Pointer to the beginning of the reserved event's data buffer, or + * NULL on error (ie not enough space). + */ +jack_midi_data_t* +jack_midi_event_reserve(void *port_buffer, + jack_nframes_t time, + size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Write an event into an event port buffer. + * + * This function is simply a wrapper for @ref jack_midi_event_reserve + * which writes the event data into the space reserved in the buffer. + * + * Clients must not write more than + * @a data_size bytes into this buffer. Clients must write normalised + * MIDI data to the port - no running status and no (1-byte) realtime + * messages interspersed with other messages (realtime messages are fine + * when they occur on their own, like other messages). + * + * Events must be written in order, sorted by their sample offsets. + * JACK will not sort the events for you, and will refuse to store + * out-of-order events. + * + * @param port_buffer Buffer to write event to. + * @param time Sample offset of event. + * @param data Message data to be written. + * @param data_size Length of @a data in bytes. + * @return 0 on success, ENOBUFS if there's not enough space in buffer for event. + */ +int +jack_midi_event_write(void *port_buffer, + jack_nframes_t time, + const jack_midi_data_t *data, + size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Get the number of events that could not be written to @a port_buffer. + * + * This function returning a non-zero value implies @a port_buffer is full. + * Currently the only way this can happen is if events are lost on port mixdown. + * + * @param port_buffer Port to receive count for. + * @returns Number of events that could not be written to @a port_buffer. + */ +uint32_t +jack_midi_get_lost_event_count(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +#ifdef __cplusplus +} +#endif + + +#endif /* __JACK_MIDIPORT_H */ + + diff --git a/extern/include/jack/ringbuffer.h b/extern/include/jack/ringbuffer.h new file mode 100644 index 00000000..cb0ca942 --- /dev/null +++ b/extern/include/jack/ringbuffer.h @@ -0,0 +1,243 @@ +/* + Copyright (C) 2000 Paul Davis + Copyright (C) 2003 Rohan Drape + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef _RINGBUFFER_H +#define _RINGBUFFER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** @file ringbuffer.h + * + * A set of library functions to make lock-free ringbuffers available + * to JACK clients. The `capture_client.c' (in the example_clients + * directory) is a fully functioning user of this API. + * + * The key attribute of a ringbuffer is that it can be safely accessed + * by two threads simultaneously -- one reading from the buffer and + * the other writing to it -- without using any synchronization or + * mutual exclusion primitives. For this to work correctly, there can + * only be a single reader and a single writer thread. Their + * identities cannot be interchanged. + */ + +typedef struct { + char *buf; + size_t len; +} +jack_ringbuffer_data_t ; + +typedef struct { + char *buf; + volatile size_t write_ptr; + volatile size_t read_ptr; + size_t size; + size_t size_mask; + int mlocked; +} +jack_ringbuffer_t ; + +/** + * Allocates a ringbuffer data structure of a specified size. The + * caller must arrange for a call to jack_ringbuffer_free() to release + * the memory associated with the ringbuffer. + * + * @param sz the ringbuffer size in bytes. + * + * @return a pointer to a new jack_ringbuffer_t, if successful; NULL + * otherwise. + */ +jack_ringbuffer_t *jack_ringbuffer_create(size_t sz); + +/** + * Frees the ringbuffer data structure allocated by an earlier call to + * jack_ringbuffer_create(). + * + * @param rb a pointer to the ringbuffer structure. + */ +void jack_ringbuffer_free(jack_ringbuffer_t *rb); + +/** + * Fill a data structure with a description of the current readable + * data held in the ringbuffer. This description is returned in a two + * element array of jack_ringbuffer_data_t. Two elements are needed + * because the data to be read may be split across the end of the + * ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be read in a contiguous fashion using the address given in the + * corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be read from the address given in + * its corresponding @a buf field. + * + * @param rb a pointer to the ringbuffer structure. + * @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. + * + */ +void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb, + jack_ringbuffer_data_t *vec); + +/** + * Fill a data structure with a description of the current writable + * space in the ringbuffer. The description is returned in a two + * element array of jack_ringbuffer_data_t. Two elements are needed + * because the space available for writing may be split across the end + * of the ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be written in a contiguous fashion using the address given in + * the corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be written to the address given in + * the corresponding @a buf field. + * + * @param rb a pointer to the ringbuffer structure. + * @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. + */ +void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb, + jack_ringbuffer_data_t *vec); + +/** + * Read data from the ringbuffer. + * + * @param rb a pointer to the ringbuffer structure. + * @param dest a pointer to a buffer where data read from the + * ringbuffer will go. + * @param cnt the number of bytes to read. + * + * @return the number of bytes read, which may range from 0 to cnt. + */ +size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt); + +/** + * Read data from the ringbuffer. Opposed to jack_ringbuffer_read() + * this function does not move the read pointer. Thus it's + * a convenient way to inspect data in the ringbuffer in a + * continous fashion. The price is that the data is copied + * into a user provided buffer. For "raw" non-copy inspection + * of the data in the ringbuffer use jack_ringbuffer_get_read_vector(). + * + * @param rb a pointer to the ringbuffer structure. + * @param dest a pointer to a buffer where data read from the + * ringbuffer will go. + * @param cnt the number of bytes to read. + * + * @return the number of bytes read, which may range from 0 to cnt. + */ +size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt); + +/** + * Advance the read pointer. + * + * After data have been read from the ringbuffer using the pointers + * returned by jack_ringbuffer_get_read_vector(), use this function to + * advance the buffer pointers, making that space available for future + * write operations. + * + * @param rb a pointer to the ringbuffer structure. + * @param cnt the number of bytes read. + */ +void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt); + +/** + * Return the number of bytes available for reading. + * + * @param rb a pointer to the ringbuffer structure. + * + * @return the number of bytes available to read. + */ +size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb); + +/** + * Lock a ringbuffer data block into memory. + * + * Uses the mlock() system call. This is not a realtime operation. + * + * @param rb a pointer to the ringbuffer structure. + */ +int jack_ringbuffer_mlock(jack_ringbuffer_t *rb); + +/** + * Reset the read and write pointers, making an empty buffer. + * + * This is not thread safe. + * + * @param rb a pointer to the ringbuffer structure. + */ +void jack_ringbuffer_reset(jack_ringbuffer_t *rb); + +/** + * Reset the internal "available" size, and read and write pointers, making an empty buffer. + * + * This is not thread safe. + * + * @param rb a pointer to the ringbuffer structure. + * @param sz the new size, that must be less than allocated size. + */ +void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz); + +/** + * Write data into the ringbuffer. + * + * @param rb a pointer to the ringbuffer structure. + * @param src a pointer to the data to be written to the ringbuffer. + * @param cnt the number of bytes to write. + * + * @return the number of bytes write, which may range from 0 to cnt + */ +size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, + size_t cnt); + +/** + * Advance the write pointer. + * + * After data have been written the ringbuffer using the pointers + * returned by jack_ringbuffer_get_write_vector(), use this function + * to advance the buffer pointer, making the data available for future + * read operations. + * + * @param rb a pointer to the ringbuffer structure. + * @param cnt the number of bytes written. + */ +void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt); + +/** + * Return the number of bytes available for writing. + * + * @param rb a pointer to the ringbuffer structure. + * + * @return the amount of free space (in bytes) available for writing. + */ +size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/extern/include/jack/session.h b/extern/include/jack/session.h new file mode 100644 index 00000000..376e4433 --- /dev/null +++ b/extern/include/jack/session.h @@ -0,0 +1,270 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004 Jack O'Quin + Copyright (C) 2010 Torben Hohn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __jack_session_h__ +#define __jack_session_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @defgroup SessionClientFunctions Session API for clients. + * @{ + */ + + +/** + * Session event type. + * + * If a client cant save templates, i might just do a normal save. + * + * There is no "quit without saving" event because a client might refuse to + * quit when it has unsaved data, but other clients may have already quit. + * This results in too much confusion, so it is unsupported. + */ +enum JackSessionEventType { + /** + * Save the session completely. + * + * The client may save references to data outside the provided directory, + * but it must do so by creating a link inside the provided directory and + * referring to that in any save files. The client must not refer to data + * files outside the provided directory directly in save files, because + * this makes it impossible for the session manager to create a session + * archive for distribution or archival. + */ + JackSessionSave = 1, + + /** + * Save the session completly, then quit. + * + * The rules for saving are exactly the same as for JackSessionSave. + */ + JackSessionSaveAndQuit = 2, + + /** + * Save a session template. + * + * A session template is a "skeleton" of the session, but without any data. + * Clients must save a session that, when restored, will create the same + * ports as a full save would have. However, the actual data contained in + * the session may not be saved (e.g. a DAW would create the necessary + * tracks, but not save the actual recorded data). + */ + JackSessionSaveTemplate = 3 +}; + +typedef enum JackSessionEventType jack_session_event_type_t; + +/** + * @ref jack_session_flags_t bits + */ +enum JackSessionFlags { + /** + * An error occured while saving. + */ + JackSessionSaveError = 0x01, + + /** + * Client needs to be run in a terminal. + */ + JackSessionNeedTerminal = 0x02 +}; + +/** + * Session flags. + */ +typedef enum JackSessionFlags jack_session_flags_t; + +struct _jack_session_event { + /** + * The type of this session event. + */ + jack_session_event_type_t type; + + /** + * Session directory path, with trailing separator. + * + * This directory is exclusive to the client; when saving the client may + * create any files it likes in this directory. + */ + const char *session_dir; + + /** + * Client UUID which must be passed to jack_client_open on session load. + * + * The client can specify this in the returned command line, or save it + * in a state file within the session directory. + */ + const char *client_uuid; + + /** + * Reply (set by client): the command line needed to restore the client. + * + * This is a platform dependent command line. It must contain + * ${SESSION_DIR} instead of the actual session directory path. More + * generally, just as in session files, clients should not include any + * paths outside the session directory here as this makes + * archival/distribution impossible. + * + * This field is set to NULL by Jack when the event is delivered to the + * client. The client must set to allocated memory that is safe to + * free(). This memory will be freed by jack_session_event_free. + */ + char *command_line; + + /** + * Reply (set by client): Session flags. + */ + jack_session_flags_t flags; + + /** + * Future flags. Set to zero for now. + */ + uint32_t future; +}; + +typedef struct _jack_session_event jack_session_event_t; + +/** + * Prototype for the client supplied function that is called + * whenever a session notification is sent via jack_session_notify(). + * + * Ownership of the memory of @a event is passed to the application. + * It must be freed using jack_session_event_free when its not used anymore. + * + * The client must promptly call jack_session_reply for this event. + * + * @param event The event structure. + * @param arg Pointer to a client supplied structure. + */ +typedef void (*JackSessionCallback)(jack_session_event_t *event, + void *arg); + +/** + * Tell the JACK server to call @a session_callback when a session event + * is to be delivered. + * + * setting more than one session_callback per process is probably a design + * error. if you have a multiclient application its more sensible to create + * a jack_client with only a session callback set. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_session_callback (jack_client_t *client, + JackSessionCallback session_callback, + void *arg) JACK_WEAK_EXPORT; + +/** + * Reply to a session event. + * + * This can either be called directly from the callback, or later from a + * different thread. For example, it is possible to push the event through a + * queue and execute the save code from the GUI thread. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_session_reply (jack_client_t *client, + jack_session_event_t *event) JACK_WEAK_EXPORT; + + +/** + * Free memory used by a jack_session_event_t. + * + * This also frees the memory used by the command_line pointer, if its non NULL. + */ +void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT; + + +/** + * Get the assigned uuid for client. + * Safe to call from callback and all other threads. + * + * The caller is responsible for calling jack_free(3) on any non-NULL + * returned value. + */ +char *jack_client_get_uuid (jack_client_t *client) JACK_WEAK_EXPORT; + +/** + * @} + */ + +/** + * @defgroup JackSessionManagerAPI API for a session manager. + * + * @{ + */ + +typedef struct { + const char *uuid; + const char *client_name; + const char *command; + jack_session_flags_t flags; +} jack_session_command_t; + +/** + * Send an event to all clients listening for session callbacks. + * + * The returned strings of the clients are accumulated and returned as an array + * of jack_session_command_t. its terminated by ret[i].uuid == NULL target == + * NULL means send to all interested clients. otherwise a clientname + */ +jack_session_command_t *jack_session_notify ( + jack_client_t* client, + const char *target, + jack_session_event_type_t type, + const char *path) JACK_WEAK_EXPORT; + +/** + * Free the memory allocated by a session command. + */ +void jack_session_commands_free (jack_session_command_t *cmds) JACK_WEAK_EXPORT; + +/** + * Reserve a client name and associate it with a UUID. + * + * When a client later calls jack_client_open() and specifies the UUID, jackd + * will assign the reserved name. This allows a session manager to know in + * advance under which client name its managed clients will appear. + * + * @return 0 on success, otherwise a non-zero error code + */ +int +jack_reserve_client_name (jack_client_t *client, + const char *name, + const char *uuid) JACK_WEAK_EXPORT; + +/** + * Find out whether a client has set up a session callback. + * + * @return 0 when the client has no session callback, 1 when it has one. + * -1 on error. + */ +int +jack_client_has_session_callback (jack_client_t *client, const char *client_name) JACK_WEAK_EXPORT; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/extern/include/jack/statistics.h b/extern/include/jack/statistics.h new file mode 100644 index 00000000..28c270d0 --- /dev/null +++ b/extern/include/jack/statistics.h @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2004 Rui Nuno Capela, Lee Revell +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public License +* as published by the Free Software Foundation; either version 2.1 +* 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this program; if not, write to the Free +* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +* 02111-1307, USA. +* +*/ + +#ifndef __statistics_h__ +#define __statistics_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * @return the maximum delay reported by the backend since + * startup or reset. When compared to the period size in usecs, this + * can be used to estimate the ideal period size for a given setup. + */ +float jack_get_max_delayed_usecs (jack_client_t *client); + +/** + * @return the delay in microseconds due to the most recent XRUN + * occurrence. This probably only makes sense when called from a @ref + * JackXRunCallback defined using jack_set_xrun_callback(). + */ +float jack_get_xrun_delayed_usecs (jack_client_t *client); + +/** + * Reset the maximum delay counter. This would be useful + * to estimate the effect that a change to the configuration of a running + * system (e.g. toggling kernel preemption) has on the delay + * experienced by JACK, without having to restart the JACK engine. + */ +void jack_reset_max_delayed_usecs (jack_client_t *client); + +#ifdef __cplusplus +} +#endif + +#endif /* __statistics_h__ */ diff --git a/extern/include/jack/systemdeps.h b/extern/include/jack/systemdeps.h new file mode 100644 index 00000000..7bec7152 --- /dev/null +++ b/extern/include/jack/systemdeps.h @@ -0,0 +1,126 @@ +/* +Copyright (C) 2004-2012 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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. + +*/ + +#ifndef __jack_systemdeps_h__ +#define __jack_systemdeps_h__ + +#ifndef POST_PACKED_STRUCTURE + + #ifdef __GNUC__ + /* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. + */ + + #define PRE_PACKED_STRUCTURE + #define POST_PACKED_STRUCTURE __attribute__((__packed__)) + + #else + + #ifdef _MSC_VER + #define PRE_PACKED_STRUCTURE1 __pragma(pack(push,1)) + #define PRE_PACKED_STRUCTURE PRE_PACKED_STRUCTURE1 + /* PRE_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the following structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. + */ + #define POST_PACKED_STRUCTURE ;__pragma(pack(pop)) + /* and POST_PACKED_STRUCTURE needs to be a macro which + restores the packing to its previous setting */ + #else + #define PRE_PACKED_STRUCTURE + #define POST_PACKED_STRUCTURE + #endif /* _MSC_VER */ + + #endif /* __GNUC__ */ + +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(GNU_WIN32) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #ifndef NOMINMAX + #define NOMINMAX + #endif + #include + + #ifdef _MSC_VER /* Microsoft compiler */ + #define __inline__ inline + #if (!defined(int8_t) && !defined(_STDINT)) + #define __int8_t_defined + #include + #endif + #elif __MINGW32__ /* MINGW */ + #include + #include + #else /* other compilers ...*/ + #include + #include + #include + #endif + + #if !defined(_PTHREAD_H) && !defined(PTHREAD_WIN32) + /** + * to make jack API independent of different thread implementations, + * we define jack_native_thread_t to HANDLE here. + */ + typedef HANDLE jack_native_thread_t; + #else + #ifdef PTHREAD_WIN32 // Added by JE - 10-10-2011 + #include // Makes sure we #include the ptw32 version ! + #endif + /** + * to make jack API independent of different thread implementations, + * we define jack_native_thread_t to pthread_t here. + */ + typedef pthread_t jack_native_thread_t; + #endif + +#endif /* _WIN32 && !__CYGWIN__ && !GNU_WIN32 */ + +#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) + + #if defined(__CYGWIN__) || defined(GNU_WIN32) + #include + #endif + #include + #include + #include + + /** + * to make jack API independent of different thread implementations, + * we define jack_native_thread_t to pthread_t here. + */ + typedef pthread_t jack_native_thread_t; + +#endif /* __APPLE__ || __linux__ || __sun__ || sun */ + +#if defined(__arm__) || defined(__ppc__) || defined(__powerpc__) + #undef POST_PACKED_STRUCTURE + #define POST_PACKED_STRUCTURE +#endif /* __arm__ || __ppc__ || __powerpc__ */ + +#endif /* __jack_systemdeps_h__ */ diff --git a/extern/include/jack/thread.h b/extern/include/jack/thread.h new file mode 100644 index 00000000..776c5206 --- /dev/null +++ b/extern/include/jack/thread.h @@ -0,0 +1,160 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __jack_thread_h__ +#define __jack_thread_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +/* use 512KB stack per thread - the default is way too high to be feasible + * with mlockall() on many systems */ +#define THREAD_STACK 524288 + +/** @file thread.h + * + * Library functions to standardize thread creation for JACK and its + * clients. These interfaces hide some system variations in the + * handling of realtime scheduling and associated privileges. + */ + +/** + * @defgroup ClientThreads Creating and managing client threads + * @{ + */ + + /** + * @returns if JACK is running with realtime scheduling, this returns + * the priority that any JACK-created client threads will run at. + * Otherwise returns -1. + */ + +int jack_client_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @returns if JACK is running with realtime scheduling, this returns + * the maximum priority that a JACK client thread should use if the thread + * is subject to realtime scheduling. Otherwise returns -1. + */ + +int jack_client_max_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Attempt to enable realtime scheduling for a thread. On some + * systems that may require special privileges. + * + * @param thread POSIX thread ID. + * @param priority requested thread priority. + * + * @returns 0, if successful; EPERM, if the calling process lacks + * required realtime privileges; otherwise some other error number. + */ +int jack_acquire_real_time_scheduling (jack_native_thread_t thread, int priority) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Create a thread for JACK or one of its clients. The thread is + * created executing @a start_routine with @a arg as its sole + * argument. + * + * @param client the JACK client for whom the thread is being created. May be + * NULL if the client is being created within the JACK server. + * @param thread place to return POSIX thread ID. + * @param priority thread priority, if realtime. + * @param realtime true for the thread to use realtime scheduling. On + * some systems that may require special privileges. + * @param start_routine function the thread calls when it starts. + * @param arg parameter passed to the @a start_routine. + * + * @returns 0, if successful; otherwise some error number. + */ +int jack_client_create_thread (jack_client_t* client, + jack_native_thread_t *thread, + int priority, + int realtime, /* boolean */ + void *(*start_routine)(void*), + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Drop realtime scheduling for a thread. + * + * @param thread POSIX thread ID. + * + * @returns 0, if successful; otherwise an error number. + */ +int jack_drop_real_time_scheduling (jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Stop the thread, waiting for the thread handler to terminate. + * + * @param thread POSIX thread ID. + * + * @returns 0, if successful; otherwise an error number. + */ +int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Kill the thread. + * + * @param thread POSIX thread ID. + * + * @returns 0, if successful; otherwise an error number. + */ + int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; + +#ifndef _WIN32 + + typedef int (*jack_thread_creator_t)(pthread_t*, + const pthread_attr_t*, + void* (*function)(void*), + void* arg); +/** + * This function can be used in very very specialized cases + * where it is necessary that client threads created by JACK + * are created by something other than pthread_create(). After + * it is used, any threads that JACK needs for the client will + * will be created by calling the function passed to this + * function. + * + * No normal application/client should consider calling this. + * The specific case for which it was created involves running + * win32/x86 plugins under Wine on Linux, where it is necessary + * that all threads that might call win32 functions are known + * to Wine. + * + * Set it to NULL to restore thread creation function. + * + * @param creator a function that creates a new thread + * + */ +void jack_set_thread_creator (jack_thread_creator_t creator) JACK_OPTIONAL_WEAK_EXPORT; + +#endif + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_thread_h__ */ diff --git a/extern/include/jack/transport.h b/extern/include/jack/transport.h new file mode 100644 index 00000000..4cec6e03 --- /dev/null +++ b/extern/include/jack/transport.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2002 Paul Davis + Copyright (C) 2003 Jack O'Quin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __jack_transport_h__ +#define __jack_transport_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @defgroup TransportControl Transport and Timebase control + * @{ + */ + +/** + * Called by the timebase master to release itself from that + * responsibility. + * + * If the timebase master releases the timebase or leaves the JACK + * graph for any reason, the JACK engine takes over at the start of + * the next process cycle. The transport state does not change. If + * rolling, it continues to play, with frame numbers as the only + * available position information. + * + * @see jack_set_timebase_callback + * + * @param client the JACK client structure. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_release_timebase (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Register (or unregister) as a slow-sync client, one that cannot + * respond immediately to transport position changes. + * + * The @a sync_callback will be invoked at the first available + * opportunity after its registration is complete. If the client is + * currently active this will be the following process cycle, + * otherwise it will be the first cycle after calling jack_activate(). + * After that, it runs according to the ::JackSyncCallback rules. + * Clients that don't set a @a sync_callback are assumed to be ready + * immediately any time the transport wants to start. + * + * @param client the JACK client structure. + * @param sync_callback is a realtime function that returns TRUE when + * the client is ready. Setting @a sync_callback to NULL declares that + * this client no longer requires slow-sync processing. + * @param arg an argument for the @a sync_callback function. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_sync_callback (jack_client_t *client, + JackSyncCallback sync_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set the timeout value for slow-sync clients. + * + * This timeout prevents unresponsive slow-sync clients from + * completely halting the transport mechanism. The default is two + * seconds. When the timeout expires, the transport starts rolling, + * even if some slow-sync clients are still unready. The @a + * sync_callbacks of these clients continue being invoked, giving them + * a chance to catch up. + * + * @see jack_set_sync_callback + * + * @param client the JACK client structure. + * @param timeout is delay (in microseconds) before the timeout expires. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_sync_timeout (jack_client_t *client, + jack_time_t timeout) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Register as timebase master for the JACK subsystem. + * + * The timebase master registers a callback that updates extended + * position information such as beats or timecode whenever necessary. + * Without this extended information, there is no need for this + * function. + * + * There is never more than one master at a time. When a new client + * takes over, the former @a timebase_callback is no longer called. + * Taking over the timebase may be done conditionally, so it fails if + * there was a master already. + * + * @param client the JACK client structure. + * @param conditional non-zero for a conditional request. + * @param timebase_callback is a realtime function that returns + * position information. + * @param arg an argument for the @a timebase_callback function. + * + * @return + * - 0 on success; + * - EBUSY if a conditional request fails because there was already a + * timebase master; + * - other non-zero error code. + */ +int jack_set_timebase_callback (jack_client_t *client, + int conditional, + JackTimebaseCallback timebase_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Reposition the transport to a new frame number. + * + * May be called at any time by any client. The new position takes + * effect in two process cycles. If there are slow-sync clients and + * the transport is already rolling, it will enter the + * ::JackTransportStarting state and begin invoking their @a + * sync_callbacks until ready. This function is realtime-safe. + * + * @see jack_transport_reposition, jack_set_sync_callback + * + * @param client the JACK client structure. + * @param frame frame number of new transport position. + * + * @return 0 if valid request, non-zero otherwise. + */ +int jack_transport_locate (jack_client_t *client, + jack_nframes_t frame) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Query the current transport state and position. + * + * This function is realtime-safe, and can be called from any thread. + * If called from the process thread, @a pos corresponds to the first + * frame of the current cycle and the state returned is valid for the + * entire cycle. + * + * @param client the JACK client structure. + * @param pos pointer to structure for returning current transport + * position; @a pos->valid will show which fields contain valid data. + * If @a pos is NULL, do not return position information. + * + * @return Current transport state. + */ +jack_transport_state_t jack_transport_query (const jack_client_t *client, + jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Return an estimate of the current transport frame, + * including any time elapsed since the last transport + * positional update. + * + * @param client the JACK client structure + */ +jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Request a new transport position. + * + * May be called at any time by any client. The new position takes + * effect in two process cycles. If there are slow-sync clients and + * the transport is already rolling, it will enter the + * ::JackTransportStarting state and begin invoking their @a + * sync_callbacks until ready. This function is realtime-safe. + * + * @see jack_transport_locate, jack_set_sync_callback + * + * @param client the JACK client structure. + * @param pos requested new transport position. + * + * @return 0 if valid request, EINVAL if position structure rejected. + */ +int jack_transport_reposition (jack_client_t *client, + const jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Start the JACK transport rolling. + * + * Any client can make this request at any time. It takes effect no + * sooner than the next process cycle, perhaps later if there are + * slow-sync clients. This function is realtime-safe. + * + * @see jack_set_sync_callback + * + * @param client the JACK client structure. + */ +void jack_transport_start (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Stop the JACK transport. + * + * Any client can make this request at any time. It takes effect on + * the next process cycle. This function is realtime-safe. + * + * @param client the JACK client structure. + */ +void jack_transport_stop (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Gets the current transport info structure (deprecated). + * + * @param client the JACK client structure. + * @param tinfo current transport info structure. The "valid" field + * describes which fields contain valid data. + * + * @deprecated This is for compatibility with the earlier transport + * interface. Use jack_transport_query(), instead. + * + * @pre Must be called from the process thread. + */ +void jack_get_transport_info (jack_client_t *client, + jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set the transport info structure (deprecated). + * + * @deprecated This function still exists for compatibility with the + * earlier transport interface, but it does nothing. Instead, define + * a ::JackTimebaseCallback. + */ +void jack_set_transport_info (jack_client_t *client, + jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_transport_h__ */ diff --git a/extern/include/jack/types.h b/extern/include/jack/types.h new file mode 100644 index 00000000..2dccf34f --- /dev/null +++ b/extern/include/jack/types.h @@ -0,0 +1,740 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004 Jack O'Quin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __jack_types_h__ +#define __jack_types_h__ + +#include + +typedef uint64_t jack_uuid_t; + +typedef int32_t jack_shmsize_t; + +/** + * Type used to represent sample frame counts. + */ +typedef uint32_t jack_nframes_t; + +/** + * Maximum value that can be stored in jack_nframes_t + */ +#define JACK_MAX_FRAMES (4294967295U) /* This should be UINT32_MAX, but C++ has a problem with that. */ + +/** + * Type used to represent the value of free running + * monotonic clock with units of microseconds. + */ +typedef uint64_t jack_time_t; + +/** + * Maximum size of @a load_init string passed to an internal client + * jack_initialize() function via jack_internal_client_load(). + */ +#define JACK_LOAD_INIT_LIMIT 1024 + +/** + * jack_intclient_t is an opaque type representing a loaded internal + * client. You may only access it using the API provided in @ref + * intclient.h "". + */ +typedef uint64_t jack_intclient_t; + +/** + * jack_port_t is an opaque type. You may only access it using the + * API provided. + */ +typedef struct _jack_port jack_port_t; + +/** + * jack_client_t is an opaque type. You may only access it using the + * API provided. + */ +typedef struct _jack_client jack_client_t; + +/** + * Ports have unique ids. A port registration callback is the only + * place you ever need to know their value. + */ +typedef uint32_t jack_port_id_t; + +typedef uint32_t jack_port_type_id_t; + +/** + * @ref jack_options_t bits + */ +enum JackOptions { + + /** + * Null value to use when no option bits are needed. + */ + JackNullOption = 0x00, + + /** + * Do not automatically start the JACK server when it is not + * already running. This option is always selected if + * \$JACK_NO_START_SERVER is defined in the calling process + * environment. + */ + JackNoStartServer = 0x01, + + /** + * Use the exact client name requested. Otherwise, JACK + * automatically generates a unique one, if needed. + */ + JackUseExactName = 0x02, + + /** + * Open with optional (char *) server_name parameter. + */ + JackServerName = 0x04, + + /** + * Load internal client from optional (char *) + * load_name. Otherwise use the @a client_name. + */ + JackLoadName = 0x08, + + /** + * Pass optional (char *) load_init string to the + * jack_initialize() entry point of an internal client. + */ + JackLoadInit = 0x10, + + /** + * pass a SessionID Token this allows the sessionmanager to identify the client again. + */ + JackSessionID = 0x20 +}; + +/** Valid options for opening an external client. */ +#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) + +/** Valid options for loading an internal client. */ +#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) + +/** + * Options for several JACK operations, formed by OR-ing together the + * relevant @ref JackOptions bits. + */ +typedef enum JackOptions jack_options_t; + +/** + * @ref jack_status_t bits + */ +enum JackStatus { + + /** + * Overall operation failed. + */ + JackFailure = 0x01, + + /** + * The operation contained an invalid or unsupported option. + */ + JackInvalidOption = 0x02, + + /** + * The desired client name was not unique. With the @ref + * JackUseExactName option this situation is fatal. Otherwise, + * the name was modified by appending a dash and a two-digit + * number in the range "-01" to "-99". The + * jack_get_client_name() function will return the exact string + * that was used. If the specified @a client_name plus these + * extra characters would be too long, the open fails instead. + */ + JackNameNotUnique = 0x04, + + /** + * The JACK server was started as a result of this operation. + * Otherwise, it was running already. In either case the caller + * is now connected to jackd, so there is no race condition. + * When the server shuts down, the client will find out. + */ + JackServerStarted = 0x08, + + /** + * Unable to connect to the JACK server. + */ + JackServerFailed = 0x10, + + /** + * Communication error with the JACK server. + */ + JackServerError = 0x20, + + /** + * Requested client does not exist. + */ + JackNoSuchClient = 0x40, + + /** + * Unable to load internal client + */ + JackLoadFailure = 0x80, + + /** + * Unable to initialize client + */ + JackInitFailure = 0x100, + + /** + * Unable to access shared memory + */ + JackShmFailure = 0x200, + + /** + * Client's protocol version does not match + */ + JackVersionError = 0x400, + + /** + * Backend error + */ + JackBackendError = 0x800, + + /** + * Client zombified failure + */ + JackClientZombie = 0x1000 +}; + +/** + * Status word returned from several JACK operations, formed by + * OR-ing together the relevant @ref JackStatus bits. + */ +typedef enum JackStatus jack_status_t; + +/** + * @ref jack_latency_callback_mode_t + */ +enum JackLatencyCallbackMode { + + /** + * Latency Callback for Capture Latency. + * Input Ports have their latency value setup. + * In the Callback the client needs to set the latency of the output ports + */ + JackCaptureLatency, + + /** + * Latency Callback for Playback Latency. + * Output Ports have their latency value setup. + * In the Callback the client needs to set the latency of the input ports + */ + JackPlaybackLatency + +}; + +/** + * Type of Latency Callback (Capture or Playback) + */ +typedef enum JackLatencyCallbackMode jack_latency_callback_mode_t; + +/** + * Prototype for the client supplied function that is called + * by the engine when port latencies need to be recalculated + * + * @param mode playback or capture latency + * @param arg pointer to a client supplied data + * + * @return zero on success, non-zero on error + */ +typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void *arg); + +/** + * the new latency API operates on Ranges. + */ +PRE_PACKED_STRUCTURE +struct _jack_latency_range +{ + /** + * minimum latency + */ + jack_nframes_t min; + /** + * maximum latency + */ + jack_nframes_t max; +} POST_PACKED_STRUCTURE; + +typedef struct _jack_latency_range jack_latency_range_t; + +/** + * Prototype for the client supplied function that is called + * by the engine anytime there is work to be done. + * + * @pre nframes == jack_get_buffer_size() + * @pre nframes == pow(2,x) + * + * @param nframes number of frames to process + * @param arg pointer to a client supplied structure + * + * @return zero on success, non-zero on error + */ +typedef int (*JackProcessCallback)(jack_nframes_t nframes, void *arg); + +/** + * Prototype for the client thread routine called + * by the engine when the client is inserted in the graph. + * + * @param arg pointer to a client supplied structure + * + */ +typedef void *(*JackThreadCallback)(void* arg); + +/** + * Prototype for the client supplied function that is called + * once after the creation of the thread in which other + * callbacks will be made. Special thread characteristics + * can be set from this callback, for example. This is a + * highly specialized callback and most clients will not + * and should not use it. + * + * @param arg pointer to a client supplied structure + * + * @return void + */ +typedef void (*JackThreadInitCallback)(void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever the processing graph is reordered. + * + * @param arg pointer to a client supplied structure + * + * @return zero on success, non-zero on error + */ +typedef int (*JackGraphOrderCallback)(void *arg); + +/** + * Prototype for the client-supplied function that is called whenever + * an xrun has occured. + * + * @see jack_get_xrun_delayed_usecs() + * + * @param arg pointer to a client supplied structure + * + * @return zero on success, non-zero on error + */ +typedef int (*JackXRunCallback)(void *arg); + +/** + * Prototype for the @a bufsize_callback that is invoked whenever the + * JACK engine buffer size changes. Although this function is called + * in the JACK process thread, the normal process cycle is suspended + * during its operation, causing a gap in the audio flow. So, the @a + * bufsize_callback can allocate storage, touch memory not previously + * referenced, and perform other operations that are not realtime + * safe. + * + * @param nframes buffer size + * @param arg pointer supplied by jack_set_buffer_size_callback(). + * + * @return zero on success, non-zero on error + */ +typedef int (*JackBufferSizeCallback)(jack_nframes_t nframes, void *arg); + +/** + * Prototype for the client supplied function that is called + * when the engine sample rate changes. + * + * @param nframes new engine sample rate + * @param arg pointer to a client supplied structure + * + * @return zero on success, non-zero on error + */ +typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever a port is registered or unregistered. + * + * @param port the ID of the port + * @param arg pointer to a client supplied data + * @param register non-zero if the port is being registered, + * zero if the port is being unregistered + */ +typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int /* register */, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever a client is registered or unregistered. + * + * @param name a null-terminated string containing the client name + * @param register non-zero if the client is being registered, + * zero if the client is being unregistered + * @param arg pointer to a client supplied structure + */ +typedef void (*JackClientRegistrationCallback)(const char* name, int /* register */, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever a port is connected or disconnected. + * + * @param a one of two ports connected or disconnected + * @param b one of two ports connected or disconnected + * @param connect non-zero if ports were connected + * zero if ports were disconnected + * @param arg pointer to a client supplied data + */ +typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); + +/** + * Prototype for the client supplied function that is called + * whenever the port name has been changed. + * + * @param port the port that has been renamed + * @param new_name the new name + * @param arg pointer to a client supplied structure + */ +typedef void (*JackPortRenameCallback)(jack_port_id_t port, const char* old_name, const char* new_name, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever jackd starts or stops freewheeling. + * + * @param starting non-zero if we start starting to freewheel, zero otherwise + * @param arg pointer to a client supplied structure + */ +typedef void (*JackFreewheelCallback)(int starting, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever jackd is shutdown. Note that after server shutdown, + * the client pointer is *not* deallocated by libjack, + * the application is responsible to properly use jack_client_close() + * to release client ressources. Warning: jack_client_close() cannot be + * safely used inside the shutdown callback and has to be called outside of + * the callback context. + * + * @param arg pointer to a client supplied structure + */ +typedef void (*JackShutdownCallback)(void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever jackd is shutdown. Note that after server shutdown, + * the client pointer is *not* deallocated by libjack, + * the application is responsible to properly use jack_client_close() + * to release client ressources. Warning: jack_client_close() cannot be + * safely used inside the shutdown callback and has to be called outside of + * the callback context. + + * @param code a status word, formed by OR-ing together the relevant @ref JackStatus bits. + * @param reason a string describing the shutdown reason (backend failure, server crash... etc...). + * Note that this string will not be available anymore after the callback returns, so possibly copy it. + * @param arg pointer to a client supplied structure + */ +typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg); + +/** + * Used for the type argument of jack_port_register() for default + * audio ports and midi ports. + */ +#define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" +#define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi" + +/** + * For convenience, use this typedef if you want to be able to change + * between float and double. You may want to typedef sample_t to + * jack_default_audio_sample_t in your application. + */ +typedef float jack_default_audio_sample_t; + +/** + * A port has a set of flags that are formed by AND-ing together the + * desired values from the list below. The flags "JackPortIsInput" and + * "JackPortIsOutput" are mutually exclusive and it is an error to use + * them both. + */ +enum JackPortFlags { + + /** + * if JackPortIsInput is set, then the port can receive + * data. + */ + JackPortIsInput = 0x1, + + /** + * if JackPortIsOutput is set, then data can be read from + * the port. + */ + JackPortIsOutput = 0x2, + + /** + * if JackPortIsPhysical is set, then the port corresponds + * to some kind of physical I/O connector. + */ + JackPortIsPhysical = 0x4, + + /** + * if JackPortCanMonitor is set, then a call to + * jack_port_request_monitor() makes sense. + * + * Precisely what this means is dependent on the client. A typical + * result of it being called with TRUE as the second argument is + * that data that would be available from an output port (with + * JackPortIsPhysical set) is sent to a physical output connector + * as well, so that it can be heard/seen/whatever. + * + * Clients that do not control physical interfaces + * should never create ports with this bit set. + */ + JackPortCanMonitor = 0x8, + + /** + * JackPortIsTerminal means: + * + * for an input port: the data received by the port + * will not be passed on or made + * available at any other port + * + * for an output port: the data available at the port + * does not originate from any other port + * + * Audio synthesizers, I/O hardware interface clients, HDR + * systems are examples of clients that would set this flag for + * their ports. + */ + JackPortIsTerminal = 0x10, + +}; + +/** + * Transport states. + */ +typedef enum { + + /* the order matters for binary compatibility */ + JackTransportStopped = 0, /**< Transport halted */ + JackTransportRolling = 1, /**< Transport playing */ + JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */ + JackTransportStarting = 3, /**< Waiting for sync ready */ + JackTransportNetStarting = 4, /**< Waiting for sync ready on the network*/ + +} jack_transport_state_t; + +typedef uint64_t jack_unique_t; /**< Unique ID (opaque) */ + +/** + * Optional struct jack_position_t fields. + */ +typedef enum { + + JackPositionBBT = 0x10, /**< Bar, Beat, Tick */ + JackPositionTimecode = 0x20, /**< External timecode */ + JackBBTFrameOffset = 0x40, /**< Frame offset of BBT information */ + JackAudioVideoRatio = 0x80, /**< audio frames per video frame */ + JackVideoFrameOffset = 0x100 /**< frame offset of first video frame */ + +} jack_position_bits_t; + +/** all valid position bits */ +#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode) +#define EXTENDED_TIME_INFO + +PRE_PACKED_STRUCTURE +struct _jack_position { + + /* these four cannot be set from clients: the server sets them */ + jack_unique_t unique_1; /**< unique ID */ + jack_time_t usecs; /**< monotonic, free-rolling */ + jack_nframes_t frame_rate; /**< current frame rate (per second) */ + jack_nframes_t frame; /**< frame number, always present */ + + jack_position_bits_t valid; /**< which other fields are valid */ + + /* JackPositionBBT fields: */ + int32_t bar; /**< current bar */ + int32_t beat; /**< current beat-within-bar */ + int32_t tick; /**< current tick-within-beat */ + double bar_start_tick; + + float beats_per_bar; /**< time signature "numerator" */ + float beat_type; /**< time signature "denominator" */ + double ticks_per_beat; + double beats_per_minute; + + /* JackPositionTimecode fields: (EXPERIMENTAL: could change) */ + double frame_time; /**< current time in seconds */ + double next_time; /**< next sequential frame_time + (unless repositioned) */ + + /* JackBBTFrameOffset fields: */ + jack_nframes_t bbt_offset; /**< frame offset for the BBT fields + (the given bar, beat, and tick + values actually refer to a time + frame_offset frames before the + start of the cycle), should + be assumed to be 0 if + JackBBTFrameOffset is not + set. If JackBBTFrameOffset is + set and this value is zero, the BBT + time refers to the first frame of this + cycle. If the value is positive, + the BBT time refers to a frame that + many frames before the start of the + cycle. */ + + /* JACK video positional data (experimental) */ + + float audio_frames_per_video_frame; /**< number of audio frames + per video frame. Should be assumed + zero if JackAudioVideoRatio is not + set. If JackAudioVideoRatio is set + and the value is zero, no video + data exists within the JACK graph */ + + jack_nframes_t video_offset; /**< audio frame at which the first video + frame in this cycle occurs. Should + be assumed to be 0 if JackVideoFrameOffset + is not set. If JackVideoFrameOffset is + set, but the value is zero, there is + no video frame within this cycle. */ + + /* For binary compatibility, new fields should be allocated from + * this padding area with new valid bits controlling access, so + * the existing structure size and offsets are preserved. */ + int32_t padding[7]; + + /* When (unique_1 == unique_2) the contents are consistent. */ + jack_unique_t unique_2; /**< unique ID */ + +} POST_PACKED_STRUCTURE; + +typedef struct _jack_position jack_position_t; + +/** + * Prototype for the @a sync_callback defined by slow-sync clients. + * When the client is active, this callback is invoked just before + * process() in the same thread. This occurs once after registration, + * then subsequently whenever some client requests a new position, or + * the transport enters the ::JackTransportStarting state. This + * realtime function must not wait. + * + * The transport @a state will be: + * + * - ::JackTransportStopped when a new position is requested; + * - ::JackTransportStarting when the transport is waiting to start; + * - ::JackTransportRolling when the timeout has expired, and the + * position is now a moving target. + * + * @param state current transport state. + * @param pos new transport position. + * @param arg the argument supplied by jack_set_sync_callback(). + * + * @return TRUE (non-zero) when ready to roll. + */ +typedef int (*JackSyncCallback)(jack_transport_state_t state, + jack_position_t *pos, + void *arg); + + +/** + * Prototype for the @a timebase_callback used to provide extended + * position information. Its output affects all of the following + * process cycle. This realtime function must not wait. + * + * This function is called immediately after process() in the same + * thread whenever the transport is rolling, or when any client has + * requested a new position in the previous cycle. The first cycle + * after jack_set_timebase_callback() is also treated as a new + * position, or the first cycle after jack_activate() if the client + * had been inactive. + * + * The timebase master may not use its @a pos argument to set @a + * pos->frame. To change position, use jack_transport_reposition() or + * jack_transport_locate(). These functions are realtime-safe, the @a + * timebase_callback can call them directly. + * + * @param state current transport state. + * @param nframes number of frames in current period. + * @param pos address of the position structure for the next cycle; @a + * pos->frame will be its frame number. If @a new_pos is FALSE, this + * structure contains extended position information from the current + * cycle. If TRUE, it contains whatever was set by the requester. + * The @a timebase_callback's task is to update the extended + * information here. + * @param new_pos TRUE (non-zero) for a newly requested @a pos, or for + * the first cycle after the @a timebase_callback is defined. + * @param arg the argument supplied by jack_set_timebase_callback(). + */ +typedef void (*JackTimebaseCallback)(jack_transport_state_t state, + jack_nframes_t nframes, + jack_position_t *pos, + int new_pos, + void *arg); + +/********************************************************************* + * The following interfaces are DEPRECATED. They are only provided + * for compatibility with the earlier JACK transport implementation. + *********************************************************************/ + +/** + * Optional struct jack_transport_info_t fields. + * + * @see jack_position_bits_t. + */ +typedef enum { + + JackTransportState = 0x1, /**< Transport state */ + JackTransportPosition = 0x2, /**< Frame number */ + JackTransportLoop = 0x4, /**< Loop boundaries (ignored) */ + JackTransportSMPTE = 0x8, /**< SMPTE (ignored) */ + JackTransportBBT = 0x10 /**< Bar, Beat, Tick */ + +} jack_transport_bits_t; + +/** + * Deprecated struct for transport position information. + * + * @deprecated This is for compatibility with the earlier transport + * interface. Use the jack_position_t struct, instead. + */ +typedef struct { + + /* these two cannot be set from clients: the server sets them */ + + jack_nframes_t frame_rate; /**< current frame rate (per second) */ + jack_time_t usecs; /**< monotonic, free-rolling */ + + jack_transport_bits_t valid; /**< which fields are legal to read */ + jack_transport_state_t transport_state; + jack_nframes_t frame; + jack_nframes_t loop_start; + jack_nframes_t loop_end; + + long smpte_offset; /**< SMPTE offset (from frame 0) */ + float smpte_frame_rate; /**< 29.97, 30, 24 etc. */ + + int bar; + int beat; + int tick; + double bar_start_tick; + + float beats_per_bar; + float beat_type; + double ticks_per_beat; + double beats_per_minute; + +} jack_transport_info_t; + + +#endif /* __jack_types_h__ */ diff --git a/extern/include/jack/weakjack.h b/extern/include/jack/weakjack.h new file mode 100644 index 00000000..652d58ab --- /dev/null +++ b/extern/include/jack/weakjack.h @@ -0,0 +1,125 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __weakjack_h__ +#define __weakjack_h__ + +/** + * @defgroup WeakLinkage Managing support for newer/older versions of JACK + * @{ One challenge faced by developers is that of taking + * advantage of new features introduced in new versions + * of [ JACK ] while still supporting older versions of + * the system. Normally, if an application uses a new + * feature in a library/API, it is unable to run on + * earlier versions of the library/API that do not + * support that feature. Such applications would either + * fail to launch or crash when an attempt to use the + * feature was made. This problem cane be solved using + * weakly-linked symbols. + * + * When a symbol in a framework is defined as weakly + * linked, the symbol does not have to be present at + * runtime for a process to continue running. The static + * linker identifies a weakly linked symbol as such in + * any code module that references the symbol. The + * dynamic linker uses this same information at runtime + * to determine whether a process can continue + * running. If a weakly linked symbol is not present in + * the framework, the code module can continue to run as + * long as it does not reference the symbol. However, if + * the symbol is present, the code can use it normally. + * + * (adapted from: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html) + * + * A concrete example will help. Suppose that someone uses a version + * of a JACK client we'll call "Jill". Jill was linked against a version + * of JACK that contains a newer part of the API (say, jack_set_latency_callback()) + * and would like to use it if it is available. + * + * When Jill is run on a system that has a suitably "new" version of + * JACK, this function will be available entirely normally. But if Jill + * is run on a system with an old version of JACK, the function isn't + * available. + * + * With normal symbol linkage, this would create a startup error whenever + * someone tries to run Jill with the "old" version of JACK. However, functions + * added to JACK after version 0.116.2 are all declared to have "weak" linkage + * which means that their abscence doesn't cause an error during program + * startup. Instead, Jill can test whether or not the symbol jack_set_latency_callback + * is null or not. If its null, it means that the JACK installed on this machine + * is too old to support this function. If its not null, then Jill can use it + * just like any other function in the API. For example: + * + * \code + * if (jack_set_latency_callback) { + * jack_set_latency_callback (jill_client, jill_latency_callback, arg); + * } + * \endcode + * + * However, there are clients that may want to use this approach to parts of the + * the JACK API that predate 0.116.2. For example, they might want to see if even + * really old basic parts of the API like jack_client_open() exist at runtime. + * + * Such clients should include before any other JACK header. + * This will make the \b entire JACK API be subject to weak linkage, so that any + * and all functions can be checked for existence at runtime. It is important + * to understand that very few clients need to do this - if you use this + * feature you should have a clear reason to do so. + * + * + */ + +#ifdef __APPLE__ +#define WEAK_ATTRIBUTE weak_import +#else +#define WEAK_ATTRIBUTE __weak__ +#endif + +#ifndef JACK_OPTIONAL_WEAK_EXPORT +/* JACK_OPTIONAL_WEAK_EXPORT needs to be a macro which + expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of + the symbol it used with. For this to work fully may + require linker arguments for the client as well. +*/ +#ifdef __GNUC__ +#define JACK_OPTIONAL_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + +#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +/* JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT needs to be a macro + which expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of the + symbol it is used with AND optionally to mark the symbol + as deprecated. For this to work fully may require + linker arguments for the client as well. +*/ +#ifdef __GNUC__ +#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((WEAK_ATTRIBUTE,__deprecated__)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + +/*@}*/ + +#endif /* weakjack */ diff --git a/extern/include/jack/weakmacros.h b/extern/include/jack/weakmacros.h new file mode 100644 index 00000000..944fddb9 --- /dev/null +++ b/extern/include/jack/weakmacros.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __weakmacros_h__ +#define __weakmacros_h__ + +/************************************************************* + * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function + * added to the JACK API after the 0.116.2 release. + * + * Functions that predate this release are marked with + * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile + * time in a variety of ways. The default definition is empty, + * so that these symbols get normal linkage. If you wish to + * use all JACK symbols with weak linkage, include + * before jack.h. + *************************************************************/ + +#ifdef __APPLE__ +#define WEAK_ATTRIBUTE weak_import +#else +#define WEAK_ATTRIBUTE __weak__ +#endif + +#ifndef JACK_WEAK_EXPORT +#ifdef __GNUC__ +/* JACK_WEAK_EXPORT needs to be a macro which + expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of + the symbol it used with. For this to work full may + require linker arguments in the client as well. +*/ + +#ifdef _WIN32 + /* + Not working with __declspec(dllexport) so normal linking + Linking with JackWeakAPI.cpp will be the preferred way. + */ + #define JACK_WEAK_EXPORT +#else + #define JACK_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) +#endif + +#else +/* Add other things here for non-gcc platforms */ + +#ifdef _WIN32 +#define JACK_WEAK_EXPORT +#endif + +#endif +#endif + +#ifndef JACK_WEAK_EXPORT +#define JACK_WEAK_EXPORT +#endif + +#ifndef JACK_OPTIONAL_WEAK_EXPORT +#define JACK_OPTIONAL_WEAK_EXPORT +#endif + +#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +#ifdef __GNUC__ +#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((__deprecated__)) +#else +/* Add other things here for non-gcc platforms */ + +#ifdef _WIN32 +#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +#endif + +#endif /* __GNUC__ */ + +#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +#endif + +#endif + +#endif /* __weakmacros_h__ */ + diff --git a/extern/include/termios.h b/extern/include/termios.h new file mode 100644 index 00000000..45bfc458 --- /dev/null +++ b/extern/include/termios.h @@ -0,0 +1,656 @@ +#ifndef _TERMIOS_H +#define _TERMIOS_H + +/* +This file intended to serve as a drop-in replacement for termios.h on Windows. +Please add/remove functionality as neeeded. +*/ + +// Not sure what is that... +#ifndef __USE_MISC +#define __USE_MISC +#endif // __USE_MISC + +/* Get the system-dependent definitions of `struct termios', `tcflag_t', + `cc_t', `speed_t', and all the macros specifying the flag bits. */ +#include + +#ifdef __USE_MISC +/* Compare a character C to a value VAL from the `c_cc' array in a + `struct termios'. If VAL is _POSIX_VDISABLE, no character can match it. */ +# define CCEQ(val, c) ((c) == (val) && (val) != _POSIX_VDISABLE) +#endif + +// Prevent Winsock.h from being included by the Windows.h header. +// This must be done if we plan to include Winsock2.h in other files. +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif // WIN32_LEAN_AND_MEAN +#include + +#include + +//#include "NtPathFromHandle.h" + +inline UINT _linuxbaudrate2windows(speed_t BaudRate) +{ + switch (BaudRate) + { + case B110: + return CBR_110; + case B300: + return CBR_300; + case B600: + return CBR_600; + case B1200: + return CBR_1200; + case B4800: + return CBR_4800; + case B2400: + return CBR_2400; + case B9600: + return CBR_9600; + case B19200: + return CBR_19200; + case B38400: + return CBR_38400; + case B57600: + return CBR_57600; + case B115200: + return CBR_115200; + default: + return 0; + } +} + +inline speed_t _windowsbaudrate2linux(UINT BaudRate) +{ + switch (BaudRate) + { + case CBR_110: + return B110; + case CBR_300: + return B300; + case CBR_600: + return B600; + case CBR_1200: + return B1200; + case CBR_4800: + return B4800; + case CBR_2400: + return B2400; + case CBR_9600: + return B9600; + case CBR_19200: + return B19200; + case CBR_38400: + return B38400; + case CBR_57600: + return B57600; + case CBR_115200: + return B115200; + default: + return 0; + } +} + +__inline speed_t cfgetospeed(const struct termios *__termios_p) +{ + return __termios_p->c_ospeed; +} + +__inline speed_t cfgetispeed(const struct termios *__termios_p) +{ + return __termios_p->c_ispeed; +} + +__inline int cfsetospeed(struct termios *__termios_p, speed_t __speed) +{ + __termios_p->c_ospeed = __speed; + return 0; +} + +__inline int cfsetispeed(struct termios *__termios_p, speed_t __speed) +{ + __termios_p->c_ispeed = __speed; + return 0; +} + +#ifdef __USE_MISC +__inline int cfsetspeed(struct termios *__termios_p, speed_t __speed) +{ + __termios_p->c_ispeed = __speed; + __termios_p->c_ospeed = __speed; + return 0; +} +#endif + +/* Put the state of FD into *TERMIOS_P. */ +__inline int tcgetattr(int __fd, struct termios *__termios_p) +{ + HANDLE hDev = (HANDLE)(intptr_t)__fd; + COMMTIMEOUTS timeouts; + DCB dcb; + speed_t speed = 0; + +//#pragma region TIMEOUTS + memset(&timeouts, 0, sizeof(COMMTIMEOUTS)); + if (!GetCommTimeouts(hDev, &timeouts)) + { + errno = EIO; + return -1; + } + + if ((timeouts.ReadIntervalTimeout == MAXDWORD)&&(timeouts.ReadTotalTimeoutConstant == 0)&&(timeouts.ReadTotalTimeoutMultiplier == 0)) + { + // Polling read. + __termios_p->c_cc[VMIN] = 0; // Minimum number of characters to read. + __termios_p->c_cc[VTIME] = 0; // Time to wait for every character read in tenths of seconds. + } + else if ((timeouts.ReadIntervalTimeout == 0)&&(timeouts.ReadTotalTimeoutConstant == 0)&&(timeouts.ReadTotalTimeoutMultiplier == 0)) + { + // Blocking read. + __termios_p->c_cc[VMIN] = 1; // Minimum number of characters to read. + __termios_p->c_cc[VTIME] = 0; // Time to wait for every character read in tenths of seconds. + } + else if ((timeouts.ReadIntervalTimeout == MAXDWORD)&&(timeouts.ReadTotalTimeoutMultiplier == MAXDWORD)) + { + // Read with timeout. + if (timeouts.ReadTotalTimeoutConstant/100 > 255) + { + errno = EINVAL; + return -1; + } + __termios_p->c_cc[VMIN] = 0; // Minimum number of characters to read. + __termios_p->c_cc[VTIME] = (cc_t)(timeouts.ReadTotalTimeoutConstant/100); // Time to wait for every character read in tenths of seconds. + } + else if ((timeouts.ReadTotalTimeoutConstant == 0)&&(timeouts.ReadTotalTimeoutMultiplier == 0)) + { + // Should be approximately equivalent... + + // Read with interbyte timeout. + if (timeouts.ReadIntervalTimeout/100 > 255) + { + errno = EINVAL; + return -1; + } + __termios_p->c_cc[VMIN] = 255; // Minimum number of characters to read. + __termios_p->c_cc[VTIME] = (cc_t)(timeouts.ReadIntervalTimeout/100); // Time to wait for every character read in tenths of seconds. + } + else + { + // Not sure what to do... + + // Read with timeout. + if (timeouts.ReadTotalTimeoutConstant/100 > 255) + { + errno = EINVAL; + return -1; + } + __termios_p->c_cc[VMIN] = 0; // Minimum number of characters to read. + __termios_p->c_cc[VTIME] = (cc_t)(timeouts.ReadTotalTimeoutConstant/100); // Time to wait for every character read in tenths of seconds. + } +//#pragma endregion + +//#pragma region DCB + memset(&dcb, 0, sizeof(DCB)); + if (!GetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } + + speed = _windowsbaudrate2linux(dcb.BaudRate); + __termios_p->c_ispeed = speed; + __termios_p->c_ospeed = speed; + + switch (dcb.Parity) + { + case NOPARITY : + __termios_p->c_cflag &= ~CMSPAR; + __termios_p->c_cflag &= ~PARENB; + __termios_p->c_cflag &= ~PARODD; + break; + case MARKPARITY : + __termios_p->c_cflag |= CMSPAR; + __termios_p->c_cflag &= ~PARENB; + __termios_p->c_cflag |= PARODD; + break; + case SPACEPARITY : + __termios_p->c_cflag |= CMSPAR; + __termios_p->c_cflag &= ~PARENB; + __termios_p->c_cflag &= ~PARODD; + break; + case ODDPARITY : + __termios_p->c_cflag &= ~CMSPAR; + __termios_p->c_cflag |= PARENB; + __termios_p->c_cflag |= PARODD; + break; + case EVENPARITY : + __termios_p->c_cflag &= ~CMSPAR; + __termios_p->c_cflag |= PARENB; + __termios_p->c_cflag &= ~PARODD; + break; + default : + errno = EINVAL; + return -1; + } + + if (dcb.fParity) + { + __termios_p->c_iflag |= INPCK; + } + else + { + __termios_p->c_iflag &= ~INPCK; + } + + if (!dcb.fErrorChar) + { + __termios_p->c_iflag |= IGNPAR; // A character with a framing or parity error will be discarded. + // This is only valid (at least for parity errors) if parity checking is enabled. + } + else + { + __termios_p->c_iflag &= ~IGNPAR; + } + + if (dcb.ErrorChar == 0) + { + __termios_p->c_iflag &= ~PARMRK; // Never mark a framing or parity error with prefix bytes. + } + else + { + __termios_p->c_iflag |= PARMRK; + } + + __termios_p->c_cflag &= ~CSIZE; // Erase the previous flag for the number of data bits. + + switch (dcb.ByteSize) + { + case 8: + __termios_p->c_cflag |= CS8; + break; + case 7: + __termios_p->c_cflag |= CS7; + break; + case 6: + __termios_p->c_cflag |= CS6; + break; + case 5: + __termios_p->c_cflag |= CS5; + break; + default : + errno = EINVAL; + return -1; + } + + switch (dcb.StopBits) + { + case ONESTOPBIT: + __termios_p->c_cflag &= ~CSTOPB; + break; + case TWOSTOPBITS: + __termios_p->c_cflag |= CSTOPB; + break; + default : + errno = EINVAL; + return -1; + } + + // Binary mode. + if (dcb.fBinary) + { + // The c_cflag member contains two options that should always be enabled, + // CLOCAL and CREAD. These will ensure that your program does not become + // the 'owner' of the port subject to sporatic job control and hangup signals, and + // also that the serial interface driver will read incoming data bytes. + __termios_p->c_cflag |= (CLOCAL | CREAD); + + // Raw input, no echo, no signals. + __termios_p->c_lflag &= ~(ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHONL | ISIG); + + // Raw input. + __termios_p->c_iflag &= ~(IGNBRK | BRKINT | INLCR | IGNCR | ICRNL); + + // Raw output. + __termios_p->c_oflag &= ~(OPOST | ONLCR | ONOCR | ONLRET | OCRNL); + } + else + { + // What should be done...? + + // The c_cflag member contains two options that should always be enabled, + // CLOCAL and CREAD. These will ensure that your program does not become + // the 'owner' of the port subject to sporatic job control and hangup signals, and + // also that the serial interface driver will read incoming data bytes. + __termios_p->c_cflag |= (CLOCAL | CREAD); + + __termios_p->c_lflag |= ICANON; + } + + // Software flow control. + if (!(dcb.fOutX||dcb.fInX)) + { + __termios_p->c_iflag &= ~(IXON | IXOFF | IXANY); + } + else + { + __termios_p->c_iflag |= (IXON | IXOFF); + } + + __termios_p->c_cc[VSTART] = dcb.XonChar; + __termios_p->c_cc[VSTOP] = dcb.XoffChar; + __termios_p->c_cc[VEOF] = dcb.EofChar; + + // Hardware flow control. + if (!dcb.fOutxCtsFlow) + { +#ifdef CRTSCTS + __termios_p->c_cflag &= ~CRTSCTS; +#endif // CRTSCTS +#ifdef CNEW_RTSCTS + __termios_p->c_cflag &= ~CNEW_RTSCTS; +#endif // CNEW_RTSCTS + } + else + { +#ifdef CRTSCTS + __termios_p->c_cflag |= CRTSCTS; +#endif // CRTSCTS +#ifdef CNEW_RTSCTS + __termios_p->c_cflag |= CNEW_RTSCTS; +#endif // CNEW_RTSCTS + } + + // The most likely scenario where this flag is useful is if the communication channel is + // configured for parity and seven bits per character. In this case, the eigth bit on every + // received character is a parity bit, not part of the data payload. The user program does + // not need to know the value of the parity bit. + __termios_p->c_iflag &= ~ISTRIP; +//#pragma endregion + + return 0; +} + +/* Set the state of FD to *TERMIOS_P. + Values for OPTIONAL_ACTIONS (TCSA*) are in . */ +__inline int tcsetattr(int __fd, int __optional_actions, const struct termios *__termios_p) +{ + HANDLE hDev = (HANDLE)(intptr_t)__fd; + COMMTIMEOUTS timeouts; +#ifdef ENABLE_O_NDELAY_WORKAROUND + DWORD ReadIntervalTimeout = 0, ReadTotalTimeoutConstant = 0, ReadTotalTimeoutMultiplier = 0, WriteTotalTimeoutConstant = 0; +#endif // ENABLE_O_NDELAY_WORKAROUND + DCB dcb; + + UNREFERENCED_PARAMETER(__optional_actions); + +//#pragma region TIMEOUTS + memset(&timeouts, 0, sizeof(COMMTIMEOUTS)); + if (!GetCommTimeouts(hDev, &timeouts)) + { + errno = EIO; + return -1; + } + + if ((__termios_p->c_cc[VMIN] == 0)&&(__termios_p->c_cc[VTIME]) == 0) + { + // Polling read. + timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutConstant = 0; timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 1; // ??? + } + else if ((__termios_p->c_cc[VMIN] == 1)&&(__termios_p->c_cc[VTIME]) == 0) + { + // Blocking read. + timeouts.ReadIntervalTimeout = 0; timeouts.ReadTotalTimeoutConstant = 0; timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; // ??? + } + else if ((__termios_p->c_cc[VMIN] == 0)&&(__termios_p->c_cc[VTIME]) > 0) + { + // Read with timeout. + if (__termios_p->c_cc[VTIME]*100 > MAXDWORD) + { + errno = EINVAL; + return -1; + } + timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutConstant = __termios_p->c_cc[VTIME]*100; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + timeouts.WriteTotalTimeoutConstant = __termios_p->c_cc[VTIME]*100; // ??? + } + else if ((__termios_p->c_cc[VMIN] == 255)&&(__termios_p->c_cc[VTIME]) > 0) + { + // Should be approximately equivalent... + + // Read with interbyte timeout. + if (__termios_p->c_cc[VTIME]*100 > MAXDWORD) + { + errno = EINVAL; + return -1; + } + timeouts.ReadIntervalTimeout = __termios_p->c_cc[VTIME]*100; timeouts.ReadTotalTimeoutConstant = 0; timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; // ??? + } + else + { + // Not sure what to do... + + // Read with interbyte timeout. + if (__termios_p->c_cc[VTIME]*100 > MAXDWORD) + { + errno = EINVAL; + return -1; + } + timeouts.ReadIntervalTimeout = __termios_p->c_cc[VTIME]*100; timeouts.ReadTotalTimeoutConstant = 0; timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; // ??? + } + + // Disable if XON/XOFF are necessary, enable if fcntl() is used together with O_NDELAY and timeouts... +#ifdef ENABLE_O_NDELAY_WORKAROUND + // Need to save the original timeouts settings for next calls of fcntl()... + + memset(&dcb, 0, sizeof(DCB)); + if (!GetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } + + // Warning : XoffLim and XonLim are just used as placeholders to save the original timeouts settings, + // they are not normally related to timeouts... + + ReadIntervalTimeout = timeouts.ReadIntervalTimeout; + ReadTotalTimeoutConstant = timeouts.ReadTotalTimeoutConstant; + ReadTotalTimeoutMultiplier = timeouts.ReadTotalTimeoutMultiplier; + WriteTotalTimeoutConstant = timeouts.WriteTotalTimeoutConstant; + if (ReadIntervalTimeout == MAXDWORD) ReadIntervalTimeout = 255*100; + else if (ReadIntervalTimeout/100 > 254) ReadIntervalTimeout = 254*100; + if (ReadTotalTimeoutConstant == MAXDWORD) ReadTotalTimeoutConstant = 255*100; + else if (ReadTotalTimeoutConstant/100 > 254) ReadTotalTimeoutConstant = 254*100; + if (ReadTotalTimeoutMultiplier == MAXDWORD) ReadTotalTimeoutMultiplier = 255*100; + else if (ReadTotalTimeoutMultiplier/100 > 254) ReadTotalTimeoutMultiplier = 254*100; + if (WriteTotalTimeoutConstant == MAXDWORD) WriteTotalTimeoutConstant = 255*100; + else if (WriteTotalTimeoutConstant/100 > 254) WriteTotalTimeoutConstant = 254*100; + dcb.XoffLim = (WORD)(((ReadIntervalTimeout/100)<<8)|(ReadTotalTimeoutConstant/100)); + dcb.XonLim = (WORD)(((ReadTotalTimeoutMultiplier/100)<<8)|(WriteTotalTimeoutConstant/100)); + if (!SetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } +#endif // ENABLE_O_NDELAY_WORKAROUND + + if (!SetCommTimeouts(hDev, &timeouts)) + { + errno = EIO; + return -1; + } +//#pragma endregion + +//#pragma region DCB + memset(&dcb, 0, sizeof(DCB)); + if (!GetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } + + // Not possible to have different c_ispeed and c_ospeed on Windows... + dcb.BaudRate = _linuxbaudrate2windows(__termios_p->c_ispeed); + if (dcb.BaudRate == 0) + { + errno = EINVAL; + return -1; + } + + switch (__termios_p->c_cflag & (CMSPAR | PARENB | PARODD)) + { + case 0: + dcb.Parity = NOPARITY; + break; + case (CMSPAR | PARODD): + dcb.Parity = MARKPARITY; + break; + case (CMSPAR): + dcb.Parity = SPACEPARITY; + break; + case (PARENB | PARODD): + dcb.Parity = ODDPARITY; + break; + case (PARENB): + dcb.Parity = EVENPARITY; + break; + default: + errno = EINVAL; + return -1; + } + + dcb.fParity = (__termios_p->c_iflag & INPCK)? TRUE: FALSE; + + if (__termios_p->c_iflag & IGNPAR) + { + dcb.fErrorChar = FALSE; // Indicates whether bytes received with parity errors are + // replaced with the character specified by the ErrorChar member. + } + else + { + dcb.fErrorChar = TRUE; + } + + if (__termios_p->c_iflag & PARMRK) + { + dcb.ErrorChar = 37; // ? + } + else + { + dcb.ErrorChar = 0; + } + + switch (__termios_p->c_cflag & CSIZE) + { + case CS8: + dcb.ByteSize = 8; + break; + case CS7: + dcb.ByteSize = 7; + break; + case CS6: + dcb.ByteSize = 6; + break; + case CS5: + dcb.ByteSize = 5; + break; + default: + errno = EINVAL; + return -1; + } + + dcb.StopBits = (__termios_p->c_cflag & CSTOPB)? TWOSTOPBITS: ONESTOPBIT; + + // Binary mode. + if (__termios_p->c_lflag & ~ICANON) + { + dcb.fBinary = TRUE; + } + else + { + dcb.fBinary = FALSE; + } + + // Software flow control. + if (!(__termios_p->c_iflag & IXON)||(__termios_p->c_iflag & IXOFF)) + { + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + } + else + { + dcb.fOutX = TRUE; + dcb.fInX = TRUE; + } + + dcb.XonChar = __termios_p->c_cc[VSTART]; + dcb.XoffChar = __termios_p->c_cc[VSTOP]; + dcb.EofChar = __termios_p->c_cc[VEOF]; + +#ifdef CRTSCTS + if (__termios_p->c_cflag & CRTSCTS) + { + dcb.fOutxCtsFlow = TRUE; + dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; + dcb.fOutxDsrFlow = TRUE; + //dcb.fDsrSensitivity = FALSE; + } + else + { + dcb.fOutxCtsFlow = FALSE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.fOutxDsrFlow = FALSE; + //dcb.fDsrSensitivity = FALSE; + } +#endif // CRTSCTS +#ifdef CNEW_RTSCTS + if (__termios_p->c_cflag & CNEW_RTSCTS) + { + dcb.fOutxCtsFlow = TRUE; + dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; + dcb.fOutxDsrFlow = TRUE; + //dcb.fDsrSensitivity = FALSE; + } + else + { + dcb.fOutxCtsFlow = FALSE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.fOutxDsrFlow = FALSE; + //dcb.fDsrSensitivity = FALSE; + } +#endif // CNEW_RTSCTS + + // Miscellaneous default options. + //dcb.fDtrControl = DTR_CONTROL_DISABLE; + //dcb.fAbortOnError = FALSE; + + // The SetCommState() function reconfigures the communications resource, but it does not affect + // the internal output and input buffers of the specified driver. The buffers are not flushed, + // and pending read and write operations are not terminated prematurely. + if (!SetCommState(hDev, &dcb)) + { + errno = EIO; + return -1; + } +//#pragma endregion + + return 0; +} + +#ifdef __USE_MISC +__inline void cfmakeraw(struct termios *__termios_p) +{ + __termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + __termios_p->c_oflag &= ~OPOST; + __termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + __termios_p->c_cflag &= ~(CSIZE | PARENB); + __termios_p->c_cflag |= CS8; +} +#endif + +#endif // _TERMIOS_H diff --git a/extern/include/unistd_extra.h b/extern/include/unistd_extra.h new file mode 100644 index 00000000..fee60dfd --- /dev/null +++ b/extern/include/unistd_extra.h @@ -0,0 +1,100 @@ +//#ifdef __MINGW32__ +// +//# include_next +// +//#else + +#ifndef UNISTD_EXTRA_H +#define UNISTD_EXTRA_H + +/* +This file intended to serve as a drop-in replacement for unistd.h on Windows. +Please add/remove functionality as neeeded. + +See http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html. +*/ + +#include +#include +#include +//#include // getopt from: http://www.pwilson.net/sample.html. +// To get Sleep(). +//#include + +// Prevent Winsock.h from being included by the Windows.h header. +// This must be done if we plan to include Winsock2.h in other files. +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif // WIN32_LEAN_AND_MEAN +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include + +#include + +#include + +//#define srandom srand +//#define random rand + +//const W_OK = 2; +//const R_OK = 4; + +//#define access _access +//#define ftruncate _chsize + +#ifndef _SSIZE_T_ +#ifndef ssize_t +#define ssize_t long +#endif // ssize_t +#endif // _SSIZE_T_ + + +__inline ssize_t read_linux(int __fd, void* __buf, size_t __nbytes) +{ + HANDLE hDev = (HANDLE)(intptr_t)__fd; + DWORD readBytes = 0; + + if (!ReadFile(hDev, __buf, (DWORD)__nbytes, &readBytes, NULL)) + { + // To be improved by checking GetLastError()... + errno = EIO; + return -1; + } + + return (ssize_t)readBytes; +} + +__inline ssize_t write_linux(int __fd, const void* __buf, size_t __nbytes) +{ + HANDLE hDev = (HANDLE)(intptr_t)__fd; + DWORD writtenBytes = 0; + + if (!WriteFile(hDev, __buf, (DWORD)__nbytes, &writtenBytes, NULL)) + { + // To be improved by checking GetLastError()... + errno = EIO; + return -1; + } + + return (ssize_t)writtenBytes; +} + +__inline int close_linux(int __fd) +{ + HANDLE hDev = (HANDLE)(intptr_t)__fd; + + if (!CloseHandle(hDev)) + { + // To be improved by checking GetLastError()... + errno = EIO; + return -1; + } + + return 0; +} + +#endif // UNISTD_EXTRA_H + +//#endif // __MINGW32__ diff --git a/extern/lib/libjack64.lib b/extern/lib/libjack64.lib new file mode 100644 index 0000000000000000000000000000000000000000..7fdbcb7dc3671be6d0a820d2dfe90f978ccde559 GIT binary patch literal 41990 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 WeFakjmaol7TltniOdi>kfd2y|M?4S! literal 0 HcmV?d00001 diff --git a/extern/lib/libjackserver64.lib b/extern/lib/libjackserver64.lib new file mode 100644 index 0000000000000000000000000000000000000000..d8385c24f9eaa61f02312ca952010c3b0cd016fe GIT binary patch literal 376052 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 literal 0 HcmV?d00001 diff --git a/generate_config.h.in b/generate_config.h.in new file mode 100644 index 00000000..f09c164e --- /dev/null +++ b/generate_config.h.in @@ -0,0 +1,56 @@ +/* CMake generates src/config.h from this.*/ + + +/* graphical user interface (using Qt) */ +#cmakedefine ENABLE_GUI 1 + +/* separate control window */ +#cmakedefine ENABLE_FLOATING_CONTROL_PANEL 1 + +/* Ecasound soundfile playback/recording */ +#cmakedefine ENABLE_ECASOUND 1 + +/* network (TCP/IP) interface */ +#cmakedefine ENABLE_IP_INTERFACE 1 + +/* Razor AHRS tracker support */ +#cmakedefine ENABLE_RAZOR 1 + +/* Polhemus Fastrak/Patriot tracker support */ +#cmakedefine ENABLE_POLHEMUS 1 + +/*?? support for isatty() ??*/ +#cmakedefine ENABLE_ISATTY 1 + +/* Name of package */ +#define PACKAGE "ssr" + +/* Version number of package */ +#define VERSION @SSR_VERSION@ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "ssr@spatialaudio.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "SSR (SoundScape Renderer)" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@SSR_VERSION@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "SSR (SoundScape Renderer) @SSR_VERSION@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "ssr" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://spatialaudio.net/ssr/" + +/* List of SSR authors */ +#define SSR_AUTHORS "Written by:\n Matthias Geier, Jens Ahrens\nScientific supervision:\n Sascha Spors\nContributions by:\n Peter Bartz, Florian Hinterleitner, Torben Hohn,\n Lukas Kaser, André Möhl, Till Rettberg, Fiete Winter\nGUI design:\n Katharina Bredies, Jonas Loh, Jens Ahrens\nLogo design:\n Fabian Hemmert" + +/* List of SSR authors (with Qt markup) */ +#define SSR_AUTHORS_QT "Written by:
 Matthias Geier, Jens Ahrens

Scientific supervision:
 Sascha Spors

Contributions by:
 Peter Bartz, Florian Hinterleitner, Torben Hohn,
 Lukas Kaser, André Möhl, Till Rettberg, Fiete Winter

GUI design:
 Katharina Bredies, Jonas Loh, Jens Ahrens

Logo design:
 Fabian Hemmert" + +/* SSR copyright notice */ +#define SSR_COPYRIGHT "Copyright © 2016 Division of Applied Acoustics, Chalmers University of Technology\nCopyright © 2014 Institut für Nachrichtentechnik, Universität Rostock\nCopyright © 2012 Quality & Usability Lab, Telekom Innovation Laboratories, TU Berlin\n\nLicense GPLv3+: GNU GPL version 3 or later \nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law." diff --git a/src/controller.h b/src/controller.h index 3b5d4053..d83b0ac8 100644 --- a/src/controller.h +++ b/src/controller.h @@ -1526,7 +1526,7 @@ Controller::_load_scene(const std::string& scene_file_name) return true; } - std::string file_extension = fs::path(scene_file_name).extension(); + std::string file_extension = fs::path(scene_file_name).extension().string(); if (file_extension == "") { @@ -2307,7 +2307,7 @@ Controller::_add_sources(Node& node { _add_audio_file_name(source_node , pathtools::make_path_relative_to_file(source.audio_file_name - , scene_file_name), source.audio_file_channel); + , scene_file_name).string(), source.audio_file_channel); } } @@ -2341,7 +2341,7 @@ Controller::_add_sources(Node& node { source_node.new_attribute("properties-file" , pathtools::make_path_relative_to_file(source.properties_file - , scene_file_name)); + , scene_file_name).string()); } }); } diff --git a/src/pathtools.h b/src/pathtools.h index a7677b4e..e0d00cfb 100644 --- a/src/pathtools.h +++ b/src/pathtools.h @@ -77,7 +77,7 @@ inline std::string make_path_relative_to_current_dir(const std::string& path auto p = fs::path{path}; if (p.is_absolute() || p == "") { - return p; + return p.string(); } return fs::relative(fs::absolute(filename).parent_path() / p).string(); } diff --git a/src/razor-ahrs/RazorAHRS.h b/src/razor-ahrs/RazorAHRS.h index 5a59d021..8f314189 100644 --- a/src/razor-ahrs/RazorAHRS.h +++ b/src/razor-ahrs/RazorAHRS.h @@ -24,7 +24,20 @@ #include #include // for write(), close(), ... #include // for speed_t, cfsetispeed(), ... +#ifdef _WIN32 +#include // for open(), ... +#include // for write(), close(), ... + +// Since open(), close(), read(), write() functions already exist on Windows but with a +// limited compatibility with Linux, we need to replace them with other versions... +#define open open_linux +#define close close_linux +#define read read_linux +#define write write_linux +#else #include // for open(), ... +#include // for write(), close(), ... +#endif // _WIN32 #include #include diff --git a/src/trackerpolhemus.cpp b/src/trackerpolhemus.cpp index c2bb060d..c865ae1f 100644 --- a/src/trackerpolhemus.cpp +++ b/src/trackerpolhemus.cpp @@ -29,12 +29,28 @@ #include // for write(), fsync(), close(), ... #include // for cfsetispeed(), ... -#include // for open(), ... #include // for std::stringstream -#include // for poll(), pollfd, ... #include // for assert() #include // std::chrono::milliseconds +#ifndef _WIN32 +#include // for open(), ... +#include // for poll(), pollfd, ... +#else +#include // for open(), ... +// Since open(), close(), read(), write() functions already exist on Windows but with a +// limited compatibility with Linux, we need to replace them with other versions... +#define open open_linux + +// Prevent Winsock.h from being included by the Windows.h header. +// This must be done if we plan to include Winsock2.h in other files. +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif // WIN32_LEAN_AND_MEAN +#include +#include +#endif // !_WIN32 + #include "api.h" // for Publisher #include "legacy_orientation.h" // for Orientation #include "trackerpolhemus.h" @@ -134,7 +150,11 @@ ssr::TrackerPolhemus::TrackerPolhemus(api::Publisher& controller assert(false); } + #ifndef _WIN32 fsync(_tracker_port); + #else + FlushFileBuffers(&_tracker_port); + #endif _start(); @@ -232,7 +252,11 @@ ssr::TrackerPolhemus::_thread() while (c != '\n') { + #ifndef _WIN32 error = poll(&fds, 1, 100); + #else + error = WSAPoll(&fds, 1, 100); + #endif if (error < 1) { From bb5fdfa5c9be9eed68bc50371eb913c74b427149 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 14:07:45 +0200 Subject: [PATCH 03/44] Make ASIO git submodule --- .gitmodules | 3 +++ CMakeLists.txt | 3 +++ extern/include/asio | 1 + 3 files changed, 7 insertions(+) create mode 160000 extern/include/asio diff --git a/.gitmodules b/.gitmodules index dd27bddd..17d1ac6a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "example-scenes"] path = example-scenes url = https://github.com/SoundScapeRenderer/example-scenes.git +[submodule "extern/include/asio"] + path = extern/include/asio + url = https://github.com/chriskohlhoff/asio.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f738322..d65e2078 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,6 +218,9 @@ if(ENABLE_IP_INTERFACE) # src/network/networksubscriber.cpp # src/network/server.cpp # ) + set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) + include_directories(${ASIO_PATH}) + AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src/legacy_network NETWORK_SOURCE_FILES) list(APPEND SOURCE_FILES ${NETWORK_SOURCE_FILES}) diff --git a/extern/include/asio b/extern/include/asio new file mode 160000 index 00000000..a71f5232 --- /dev/null +++ b/extern/include/asio @@ -0,0 +1 @@ +Subproject commit a71f5232d207b4f3bbd253eb1041e30b5e4ea606 From 8761ab4a5482d1d949c516c76b0b396e7b595350 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 14:19:42 +0200 Subject: [PATCH 04/44] move jack headers --- extern/include/jack/control.h | 631 ------------- extern/include/jack/intclient.h | 130 --- extern/include/jack/jack.h | 1470 ------------------------------ extern/include/jack/jslist.h | 293 ------ extern/include/jack/midiport.h | 184 ---- extern/include/jack/ringbuffer.h | 243 ----- extern/include/jack/session.h | 270 ------ extern/include/jack/statistics.h | 57 -- extern/include/jack/systemdeps.h | 126 --- extern/include/jack/thread.h | 160 ---- extern/include/jack/transport.h | 247 ----- extern/include/jack/types.h | 740 --------------- extern/include/jack/weakjack.h | 125 --- extern/include/jack/weakmacros.h | 97 -- 14 files changed, 4773 deletions(-) delete mode 100644 extern/include/jack/control.h delete mode 100644 extern/include/jack/intclient.h delete mode 100644 extern/include/jack/jack.h delete mode 100644 extern/include/jack/jslist.h delete mode 100644 extern/include/jack/midiport.h delete mode 100644 extern/include/jack/ringbuffer.h delete mode 100644 extern/include/jack/session.h delete mode 100644 extern/include/jack/statistics.h delete mode 100644 extern/include/jack/systemdeps.h delete mode 100644 extern/include/jack/thread.h delete mode 100644 extern/include/jack/transport.h delete mode 100644 extern/include/jack/types.h delete mode 100644 extern/include/jack/weakjack.h delete mode 100644 extern/include/jack/weakmacros.h diff --git a/extern/include/jack/control.h b/extern/include/jack/control.h deleted file mode 100644 index 33cd77b1..00000000 --- a/extern/include/jack/control.h +++ /dev/null @@ -1,631 +0,0 @@ -/* -*- Mode: C ; c-basic-offset: 4 -*- */ -/* - JACK control API - - Copyright (C) 2008 Nedko Arnaudov - Copyright (C) 2008 GRAME - - 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; version 2 of the License. - - 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. - -*/ -/** - * @file jack/control.h - * @ingroup publicheader - * @brief JACK control API - * - */ - -#ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED -#define JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED - -#include -#include -#include -#if !defined(sun) && !defined(__sun__) -#include -#endif - -/** Parameter types, intentionally similar to jack_driver_param_type_t */ -typedef enum -{ - JackParamInt = 1, /**< @brief value type is a signed integer */ - JackParamUInt, /**< @brief value type is an unsigned integer */ - JackParamChar, /**< @brief value type is a char */ - JackParamString, /**< @brief value type is a string with max size of ::JACK_PARAM_STRING_MAX+1 chars */ - JackParamBool, /**< @brief value type is a boolean */ -} jackctl_param_type_t; - -/** Driver types */ -typedef enum -{ - JackMaster = 1, /**< @brief master driver */ - JackSlave /**< @brief slave driver */ -} jackctl_driver_type_t; - -/** @brief Max value that jackctl_param_type_t type can have */ -#define JACK_PARAM_MAX (JackParamBool + 1) - -/** @brief Max length of string parameter value, excluding terminating null char */ -#define JACK_PARAM_STRING_MAX 127 - -/** @brief Type for parameter value */ -/* intentionally similar to jack_driver_param_value_t */ -union jackctl_parameter_value -{ - uint32_t ui; /**< @brief member used for ::JackParamUInt */ - int32_t i; /**< @brief member used for ::JackParamInt */ - char c; /**< @brief member used for ::JackParamChar */ - char str[JACK_PARAM_STRING_MAX + 1]; /**< @brief member used for ::JackParamString */ - bool b; /**< @brief member used for ::JackParamBool */ -}; - -/** opaque type for server object */ -typedef struct jackctl_server jackctl_server_t; - -/** opaque type for driver object */ -typedef struct jackctl_driver jackctl_driver_t; - -/** opaque type for internal client object */ -typedef struct jackctl_internal jackctl_internal_t; - -/** opaque type for parameter object */ -typedef struct jackctl_parameter jackctl_parameter_t; - -/** opaque type for sigmask object */ -typedef struct jackctl_sigmask jackctl_sigmask_t; - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} /* Adjust editor indent */ -#endif - -/** - * @defgroup ControlAPI The API for starting and controlling a JACK server - * @{ - */ - -/** - * Call this function to setup process signal handling. As a general - * rule, it is required for proper operation for the server object. - * - * @param flags signals setup flags, use 0 for none. Currently no - * flags are defined - * - * @return the configurated signal set. - */ -jackctl_sigmask_t * -jackctl_setup_signals( - unsigned int flags); - -/** - * Call this function to wait on a signal set. - * - * @param signals signals set to wait on - */ -void -jackctl_wait_signals( - jackctl_sigmask_t * signals); - -/** - * Call this function to create server object. - * - * @param on_device_acquire - Optional callback to be called before device is acquired. If false is returned, device usage will fail - * @param on_device_release - Optional callback to be called after device is released. - * - * @return server object handle, NULL if creation of server object - * failed. Successfully created server object must be destroyed with - * paired call to ::jackctl_server_destroy - */ -jackctl_server_t * -jackctl_server_create( - bool (* on_device_acquire)(const char * device_name), - void (* on_device_release)(const char * device_name)); - -/** - * Call this function to destroy server object. - * - * @param server server object handle to destroy - */ -void -jackctl_server_destroy( - jackctl_server_t * server); - -/** - * Call this function to open JACK server - * - * @param server server object handle - * @param driver driver to use - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_open( - jackctl_server_t * server, - jackctl_driver_t * driver); - -/** - * Call this function to start JACK server - * - * @param server server object handle - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_start( - jackctl_server_t * server); - -/** - * Call this function to stop JACK server - * - * @param server server object handle - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_stop( - jackctl_server_t * server); - -/** - * Call this function to close JACK server - * - * @param server server object handle - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_close( - jackctl_server_t * server); - -/** - * Call this function to get list of available drivers. List node data - * pointers is a driver object handle (::jackctl_driver_t). - * - * @param server server object handle to get drivers for - * - * @return Single linked list of driver object handles. Must not be - * modified. Always same for same server object. - */ -const JSList * -jackctl_server_get_drivers_list( - jackctl_server_t * server); - -/** - * Call this function to get list of server parameters. List node data - * pointers is a parameter object handle (::jackctl_parameter_t). - * - * @param server server object handle to get parameters for - * - * @return Single linked list of parameter object handles. Must not be - * modified. Always same for same server object. - */ -const JSList * -jackctl_server_get_parameters( - jackctl_server_t * server); - -/** - * Call this function to get list of available internal clients. List node data - * pointers is a internal client object handle (::jackctl_internal_t). - * - * @param server server object handle to get internal clients for - * - * @return Single linked list of internal client object handles. Must not be - * modified. Always same for same server object. - */ -const JSList * -jackctl_server_get_internals_list( - jackctl_server_t * server); - -/** - * Call this function to load one internal client. - * (can be used when the server is running) - * - * @param server server object handle - * @param internal internal to use - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_load_internal( - jackctl_server_t * server, - jackctl_internal_t * internal); - -/** - * Call this function to unload one internal client. - * (can be used when the server is running) - * - * @param server server object handle - * @param internal internal to unload - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_unload_internal( - jackctl_server_t * server, - jackctl_internal_t * internal); - -/** - * Call this function to add a slave in the driver slave list. - * (cannot be used when the server is running that is between - * jackctl_server_start and jackctl_server_stop) - * - * @param server server object handle - * @param driver driver to add in the driver slave list. - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_add_slave(jackctl_server_t * server, - jackctl_driver_t * driver); - -/** - * Call this function to remove a slave from the driver slave list. - * (cannot be used when the server is running that is between - * jackctl_server_start and jackctl_server_stop) - * - * @param server server object handle - * @param driver driver to remove from the driver slave list. - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_remove_slave(jackctl_server_t * server, - jackctl_driver_t * driver); - -/** - * Call this function to switch master driver. - * - * @param server server object handle - * @param driver driver to switch to - * - * @return success status: true - success, false - fail - */ -bool -jackctl_server_switch_master(jackctl_server_t * server, - jackctl_driver_t * driver); - - -/** - * Call this function to get name of driver. - * - * @param driver driver object handle to get name of - * - * @return driver name. Must not be modified. Always same for same - * driver object. - */ -const char * -jackctl_driver_get_name( - jackctl_driver_t * driver); - -/** - * Call this function to get type of driver. - * - * @param driver driver object handle to get name of - * - * @return driver type. Must not be modified. Always same for same - * driver object. - */ -jackctl_driver_type_t -jackctl_driver_get_type( - jackctl_driver_t * driver); - -/** - * Call this function to get list of driver parameters. List node data - * pointers is a parameter object handle (::jackctl_parameter_t). - * - * @param driver driver object handle to get parameters for - * - * @return Single linked list of parameter object handles. Must not be - * modified. Always same for same driver object. - */ -const JSList * -jackctl_driver_get_parameters( - jackctl_driver_t * driver); - -/** - * Call this function to parse parameters for a driver. - * - * @param driver driver object handle - * @param argc parameter list len - * @param argv parameter list, as an array of char* - * - * @return success status: true - success, false - fail - */ -int -jackctl_driver_params_parse( - jackctl_driver_t * driver, - int argc, - char* argv[]); - -/** - * Call this function to get name of internal client. - * - * @param internal internal object handle to get name of - * - * @return internal name. Must not be modified. Always same for same - * internal object. - */ -const char * -jackctl_internal_get_name( - jackctl_internal_t * internal); - -/** - * Call this function to get list of internal parameters. List node data - * pointers is a parameter object handle (::jackctl_parameter_t). - * - * @param internal internal object handle to get parameters for - * - * @return Single linked list of parameter object handles. Must not be - * modified. Always same for same internal object. - */ -const JSList * -jackctl_internal_get_parameters( - jackctl_internal_t * internal); - -/** - * Call this function to get parameter name. - * - * @param parameter parameter object handle to get name of - * - * @return parameter name. Must not be modified. Always same for same - * parameter object. - */ -const char * -jackctl_parameter_get_name( - jackctl_parameter_t * parameter); - -/** - * Call this function to get parameter short description. - * - * @param parameter parameter object handle to get short description of - * - * @return parameter short description. Must not be modified. Always - * same for same parameter object. - */ -const char * -jackctl_parameter_get_short_description( - jackctl_parameter_t * parameter); - -/** - * Call this function to get parameter long description. - * - * @param parameter parameter object handle to get long description of - * - * @return parameter long description. Must not be modified. Always - * same for same parameter object. - */ -const char * -jackctl_parameter_get_long_description( - jackctl_parameter_t * parameter); - -/** - * Call this function to get parameter type. - * - * @param parameter parameter object handle to get type of - * - * @return parameter type. Always same for same parameter object. - */ -jackctl_param_type_t -jackctl_parameter_get_type( - jackctl_parameter_t * parameter); - -/** - * Call this function to get parameter character. - * - * @param parameter parameter object handle to get character of - * - * @return character. - */ -char -jackctl_parameter_get_id( - jackctl_parameter_t * parameter); - -/** - * Call this function to check whether parameter has been set, or its - * default value is being used. - * - * @param parameter parameter object handle to check - * - * @return true - parameter is set, false - parameter is using default - * value. - */ -bool -jackctl_parameter_is_set( - jackctl_parameter_t * parameter); - -/** - * Call this function to reset parameter to its default value. - * - * @param parameter parameter object handle to reset value of - * - * @return success status: true - success, false - fail - */ -bool -jackctl_parameter_reset( - jackctl_parameter_t * parameter); - -/** - * Call this function to get parameter value. - * - * @param parameter parameter object handle to get value of - * - * @return parameter value. - */ -union jackctl_parameter_value -jackctl_parameter_get_value( - jackctl_parameter_t * parameter); - -/** - * Call this function to set parameter value. - * - * @param parameter parameter object handle to get value of - * @param value_ptr pointer to variable containing parameter value - * - * @return success status: true - success, false - fail - */ -bool -jackctl_parameter_set_value( - jackctl_parameter_t * parameter, - const union jackctl_parameter_value * value_ptr); - -/** - * Call this function to get parameter default value. - * - * @param parameter parameter object handle to get default value of - * - * @return parameter default value. - */ -union jackctl_parameter_value -jackctl_parameter_get_default_value( - jackctl_parameter_t * parameter); - -/** - * Call this function check whether parameter has range constraint. - * - * @param parameter object handle of parameter to check - * - * @return whether parameter has range constraint. - */ -bool -jackctl_parameter_has_range_constraint( - jackctl_parameter_t * parameter); - -/** - * Call this function check whether parameter has enumeration constraint. - * - * @param parameter object handle of parameter to check - * - * @return whether parameter has enumeration constraint. - */ -bool -jackctl_parameter_has_enum_constraint( - jackctl_parameter_t * parameter); - -/** - * Call this function get how many enumeration values parameter has. - * - * @param parameter object handle of parameter - * - * @return number of enumeration values - */ -uint32_t -jackctl_parameter_get_enum_constraints_count( - jackctl_parameter_t * parameter); - -/** - * Call this function to get parameter enumeration value. - * - * @param parameter object handle of parameter - * @param index index of parameter enumeration value - * - * @return enumeration value. - */ -union jackctl_parameter_value -jackctl_parameter_get_enum_constraint_value( - jackctl_parameter_t * parameter, - uint32_t index); - -/** - * Call this function to get parameter enumeration value description. - * - * @param parameter object handle of parameter - * @param index index of parameter enumeration value - * - * @return enumeration value description. - */ -const char * -jackctl_parameter_get_enum_constraint_description( - jackctl_parameter_t * parameter, - uint32_t index); - -/** - * Call this function to get parameter range. - * - * @param parameter object handle of parameter - * @param min_ptr pointer to variable receiving parameter minimum value - * @param max_ptr pointer to variable receiving parameter maximum value - */ -void -jackctl_parameter_get_range_constraint( - jackctl_parameter_t * parameter, - union jackctl_parameter_value * min_ptr, - union jackctl_parameter_value * max_ptr); - -/** - * Call this function to check whether parameter constraint is strict, - * i.e. whether supplying non-matching value will not work for sure. - * - * @param parameter parameter object handle to check - * - * @return whether parameter constraint is strict. - */ -bool -jackctl_parameter_constraint_is_strict( - jackctl_parameter_t * parameter); - -/** - * Call this function to check whether parameter has fake values, - * i.e. values have no user meaningful meaning and only value - * description is meaningful to user. - * - * @param parameter parameter object handle to check - * - * @return whether parameter constraint is strict. - */ -bool -jackctl_parameter_constraint_is_fake_value( - jackctl_parameter_t * parameter); - -/** - * Call this function to log an error message. - * - * @param format string - */ -void -jack_error( - const char *format, - ...); - -/** - * Call this function to log an information message. - * - * @param format string - */ -void -jack_info( - const char *format, - ...); - -/** - * Call this function to log an information message but only when - * verbose mode is enabled. - * - * @param format string - */ -void -jack_log( - const char *format, - ...); - -/* @} */ - -#if 0 -{ /* Adjust editor indent */ -#endif -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* #ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED */ diff --git a/extern/include/jack/intclient.h b/extern/include/jack/intclient.h deleted file mode 100644 index 4c126d74..00000000 --- a/extern/include/jack/intclient.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -* Copyright (C) 2004 Jack O'Quin -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#ifndef __jack_intclient_h__ -#define __jack_intclient_h__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include - -/** - * Get an internal client's name. This is useful when @ref - * JackUseExactName was not specified on jack_internal_client_load() - * and @ref JackNameNotUnique status was returned. In that case, the - * actual name will differ from the @a client_name requested. - * - * @param client requesting JACK client's handle. - * - * @param intclient handle returned from jack_internal_client_load() - * or jack_internal_client_handle(). - * - * @return NULL if unsuccessful, otherwise pointer to the internal - * client name obtained from the heap via malloc(). The caller should - * jack_free() this storage when no longer needed. - */ -char *jack_get_internal_client_name (jack_client_t *client, - jack_intclient_t intclient); - -/** - * Return the @ref jack_intclient_t handle for an internal client - * running in the JACK server. - * - * @param client requesting JACK client's handle. - * - * @param client_name for the internal client of no more than - * jack_client_name_size() characters. The name scope is local to the - * current server. - * - * @param status (if non-NULL) an address for JACK to return - * information from this operation. This status word is formed by - * OR-ing together the relevant @ref JackStatus bits. - * - * @return Opaque internal client handle if successful. If 0, the - * internal client was not found, and @a *status includes the @ref - * JackNoSuchClient and @ref JackFailure bits. - */ -jack_intclient_t jack_internal_client_handle (jack_client_t *client, - const char *client_name, - jack_status_t *status); - -/** - * Load an internal client into the JACK server. - * - * Internal clients run inside the JACK server process. They can use - * most of the same functions as external clients. Each internal - * client is built as a shared object module, which must declare - * jack_initialize() and jack_finish() entry points called at load and - * unload times. See @ref inprocess.c for an example. - * - * @param client loading JACK client's handle. - * - * @param client_name of at most jack_client_name_size() characters - * for the internal client to load. The name scope is local to the - * current server. - * - * @param options formed by OR-ing together @ref JackOptions bits. - * Only the @ref JackLoadOptions bits are valid. - * - * @param status (if non-NULL) an address for JACK to return - * information from the load operation. This status word is formed by - * OR-ing together the relevant @ref JackStatus bits. - * - * Optional parameters: depending on corresponding [@a options - * bits] additional parameters may follow @a status (in this order). - * - * @arg [@ref JackLoadName] (char *) load_name is the shared - * object file from which to load the new internal client (otherwise - * use the @a client_name). - * - * @arg [@ref JackLoadInit] (char *) load_init an arbitary - * string passed to the internal client's jack_initialize() routine - * (otherwise NULL), of no more than @ref JACK_LOAD_INIT_LIMIT bytes. - * - * @return Opaque internal client handle if successful. If this is 0, - * the load operation failed, the internal client was not loaded, and - * @a *status includes the @ref JackFailure bit. - */ -jack_intclient_t jack_internal_client_load (jack_client_t *client, - const char *client_name, - jack_options_t options, - jack_status_t *status, ...); -/** - * Unload an internal client from a JACK server. This calls the - * intclient's jack_finish() entry point then removes it. See @ref - * inprocess.c for an example. - * - * @param client unloading JACK client's handle. - * - * @param intclient handle returned from jack_internal_client_load() or - * jack_internal_client_handle(). - * - * @return 0 if successful, otherwise @ref JackStatus bits. - */ -jack_status_t jack_internal_client_unload (jack_client_t *client, - jack_intclient_t intclient); - -#ifdef __cplusplus -} -#endif - -#endif /* __jack_intclient_h__ */ diff --git a/extern/include/jack/jack.h b/extern/include/jack/jack.h deleted file mode 100644 index bf50e602..00000000 --- a/extern/include/jack/jack.h +++ /dev/null @@ -1,1470 +0,0 @@ -/* - Copyright (C) 2001 Paul Davis - Copyright (C) 2004 Jack O'Quin - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __jack_h__ -#define __jack_h__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include -#include -#include - -/** - * Note: More documentation can be found in jack/types.h. - */ - - /************************************************************* - * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function - * added to the JACK API after the 0.116.2 release. - * - * Functions that predate this release are marked with - * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile - * time in a variety of ways. The default definition is empty, - * so that these symbols get normal linkage. If you wish to - * use all JACK symbols with weak linkage, include - * before jack.h. - *************************************************************/ - -#include - -/** - * Call this function to get version of the JACK, in form of several numbers - * - * @param major_ptr pointer to variable receiving major version of JACK. - * - * @param minor_ptr pointer to variable receiving minor version of JACK. - * - * @param major_ptr pointer to variable receiving micro version of JACK. - * - * @param major_ptr pointer to variable receiving protocol version of JACK. - * - */ -void -jack_get_version( - int *major_ptr, - int *minor_ptr, - int *micro_ptr, - int *proto_ptr) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Call this function to get version of the JACK, in form of a string - * - * @return Human readable string describing JACK version being used. - * - */ -const char * -jack_get_version_string(void) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @defgroup ClientFunctions Creating & manipulating clients - * @{ - */ - -/** - * Open an external client session with a JACK server. This interface - * is more complex but more powerful than jack_client_new(). With it, - * clients may choose which of several servers to connect, and control - * whether and how to start the server automatically, if it was not - * already running. There is also an option for JACK to generate a - * unique client name, when necessary. - * - * @param client_name of at most jack_client_name_size() characters. - * The name scope is local to each server. Unless forbidden by the - * @ref JackUseExactName option, the server will modify this name to - * create a unique variant, if needed. - * - * @param options formed by OR-ing together @ref JackOptions bits. - * Only the @ref JackOpenOptions bits are allowed. - * - * @param status (if non-NULL) an address for JACK to return - * information from the open operation. This status word is formed by - * OR-ing together the relevant @ref JackStatus bits. - * - * - * Optional parameters: depending on corresponding [@a options - * bits] additional parameters may follow @a status (in this order). - * - * @arg [@ref JackServerName] (char *) server_name selects - * from among several possible concurrent server instances. Server - * names are unique to each user. If unspecified, use "default" - * unless \$JACK_DEFAULT_SERVER is defined in the process environment. - * - * @return Opaque client handle if successful. If this is NULL, the - * open operation failed, @a *status includes @ref JackFailure and the - * caller is not a JACK client. - */ -jack_client_t * jack_client_open (const char *client_name, - jack_options_t options, - jack_status_t *status, ...) JACK_OPTIONAL_WEAK_EXPORT; - -/** -* \bold THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN -* NEW JACK CLIENTS -* -* @deprecated Please use jack_client_open(). -*/ -jack_client_t * jack_client_new (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * Disconnects an external client from a JACK server. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_client_close (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the maximum number of characters in a JACK client name - * including the final NULL character. This value is a constant. - */ -int jack_client_name_size (void) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return pointer to actual client name. This is useful when @ref - * JackUseExactName is not specified on open and @ref - * JackNameNotUnique status was returned. In that case, the actual - * name will differ from the @a client_name requested. - */ -char * jack_get_client_name (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Get the session ID for a client name. - * - * The session manager needs this to reassociate a client name to the session_id. - * - * The caller is responsible for calling jack_free(3) on any non-NULL - * returned value. - */ -char *jack_get_uuid_for_client_name (jack_client_t *client, - const char *client_name) JACK_WEAK_EXPORT; - -/** - * Get the client name for a session_id. - * - * In order to snapshot the graph connections, the session manager needs to map - * session_ids to client names. - * - * The caller is responsible for calling jack_free(3) on any non-NULL - * returned value. - */ -char *jack_get_client_name_by_uuid (jack_client_t *client, - const char *client_uuid ) JACK_WEAK_EXPORT; - -/** - * Load an internal client into the Jack server. - * - * Internal clients run inside the JACK server process. They can use - * most of the same functions as external clients. Each internal - * client must declare jack_initialize() and jack_finish() entry - * points, called at load and unload times. See inprocess.c for an - * example of how to write an internal client. - * - * @deprecated Please use jack_internal_client_load(). - * - * @param client_name of at most jack_client_name_size() characters. - * - * @param load_name of a shared object file containing the code for - * the new client. - * - * @param load_init an arbitary string passed to the jack_initialize() - * routine of the new client (may be NULL). - * - * @return 0 if successful. - */ -int jack_internal_client_new (const char *client_name, - const char *load_name, - const char *load_init) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * Remove an internal client from a JACK server. - * - * @deprecated Please use jack_internal_client_unload(). - */ -void jack_internal_client_close (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * Tell the Jack server that the program is ready to start processing - * audio. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_activate (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the Jack server to remove this @a client from the process - * graph. Also, disconnect all ports belonging to it, since inactive - * clients have no port connections. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_deactivate (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return pid of client. If not available, 0 will be returned. - */ -int jack_get_client_pid (const char *name) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the pthread ID of the thread running the JACK client side - * real-time code. - */ -jack_native_thread_t jack_client_thread_id (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -/** - * @param client pointer to JACK client structure. - * - * Check if the JACK subsystem is running with -R (--realtime). - * - * @return 1 if JACK is running realtime, 0 otherwise - */ -int jack_is_realtime (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @defgroup NonCallbackAPI The non-callback API - * @{ - */ - -/** - * \bold THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN - * NEW JACK CLIENTS. - * - * @deprecated Please use jack_cycle_wait() and jack_cycle_signal() functions. - */ -jack_nframes_t jack_thread_wait (jack_client_t *client, int status) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Wait until this JACK client should process data. - * - * @param client - pointer to a JACK client structure - * - * @return the number of frames of data to process - */ -jack_nframes_t jack_cycle_wait (jack_client_t* client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Signal next clients in the graph. - * - * @param client - pointer to a JACK client structure - * @param status - if non-zero, calling thread should exit - */ -void jack_cycle_signal (jack_client_t* client, int status) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the Jack server to call @a thread_callback in the RT thread. - * Typical use are in conjunction with @a jack_cycle_wait and @a jack_cycle_signal functions. - * The code in the supplied function must be suitable for real-time - * execution. That means that it cannot call functions that might - * block for a long time. This includes malloc, free, printf, - * pthread_mutex_lock, sleep, wait, poll, select, pthread_join, - * pthread_cond_wait, etc, etc. See - * http://jackit.sourceforge.net/docs/design/design.html#SECTION00411000000000000000 - * for more information. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code. -*/ -int jack_set_process_thread(jack_client_t* client, JackThreadCallback thread_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -/** - * @defgroup ClientCallbacks Setting Client Callbacks - * @{ - */ - -/** - * Tell JACK to call @a thread_init_callback once just after - * the creation of the thread in which all other callbacks - * will be handled. - * - * The code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code, causing JACK - * to remove that client from the process() graph. - */ -int jack_set_thread_init_callback (jack_client_t *client, - JackThreadInitCallback thread_init_callback, - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @param client pointer to JACK client structure. - * @param function The jack_shutdown function pointer. - * @param arg The arguments for the jack_shutdown function. - * - * Register a function (and argument) to be called if and when the - * JACK server shuts down the client thread. The function must - * be written as if it were an asynchonrous POSIX signal - * handler --- use only async-safe functions, and remember that it - * is executed from another thread. A typical function might - * set a flag or write to a pipe so that the rest of the - * application knows that the JACK client thread has shut - * down. - * - * NOTE: clients do not need to call this. It exists only - * to help more complex clients understand what is going - * on. It should be called before jack_client_activate(). - * - * NOTE: if a client calls this AND jack_on_info_shutdown(), then - * in case of a client thread shutdown, the callback - * passed to this function will not be called, and the one passed to - * jack_on_info_shutdown() will. - * - * NOTE: application should typically signal another thread to correctly - * finish cleanup, that is by calling "jack_client_close" - * (since "jack_client_close" cannot be called directly in the context - * of the thread that calls the shutdown callback). - */ -void jack_on_shutdown (jack_client_t *client, - JackShutdownCallback shutdown_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @param client pointer to JACK client structure. - * @param function The jack_info_shutdown function pointer. - * @param arg The arguments for the jack_info_shutdown function. - * - * Register a function (and argument) to be called if and when the - * JACK server shuts down the client thread. The function must - * be written as if it were an asynchonrous POSIX signal - * handler --- use only async-safe functions, and remember that it - * is executed from another thread. A typical function might - * set a flag or write to a pipe so that the rest of the - * application knows that the JACK client thread has shut - * down. - * - * NOTE: clients do not need to call this. It exists only - * to help more complex clients understand what is going - * on. It should be called before jack_client_activate(). - * - * NOTE: if a client calls this AND jack_on_shutdown(), then - * in case of a client thread shutdown, the callback passed to - * jack_on_info_shutdown() will be called. - * - * NOTE: application should typically signal another thread to correctly - * finish cleanup, that is by calling "jack_client_close" - * (since "jack_client_close" cannot be called directly in the context - * of the thread that calls the shutdown callback). - */ -void jack_on_info_shutdown (jack_client_t *client, - JackInfoShutdownCallback shutdown_callback, void *arg) JACK_WEAK_EXPORT; - -/** - * Tell the Jack server to call @a process_callback whenever there is - * work be done, passing @a arg as the second argument. - * - * The code in the supplied function must be suitable for real-time - * execution. That means that it cannot call functions that might - * block for a long time. This includes malloc, free, printf, - * pthread_mutex_lock, sleep, wait, poll, select, pthread_join, - * pthread_cond_wait, etc, etc. See - * http://jackit.sourceforge.net/docs/design/design.html#SECTION00411000000000000000 - * for more information. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_set_process_callback (jack_client_t *client, - JackProcessCallback process_callback, - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the Jack server to call @a freewheel_callback - * whenever we enter or leave "freewheel" mode, passing @a - * arg as the second argument. The first argument to the - * callback will be non-zero if JACK is entering freewheel - * mode, and zero otherwise. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_set_freewheel_callback (jack_client_t *client, - JackFreewheelCallback freewheel_callback, - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell JACK to call @a bufsize_callback whenever the size of the the - * buffer that will be passed to the @a process_callback is about to - * change. Clients that depend on knowing the buffer size must supply - * a @a bufsize_callback before activating themselves. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @param client pointer to JACK client structure. - * @param bufsize_callback function to call when the buffer size changes. - * @param arg argument for @a bufsize_callback. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_buffer_size_callback (jack_client_t *client, - JackBufferSizeCallback bufsize_callback, - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the Jack server to call @a srate_callback whenever the system - * sample rate changes. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_sample_rate_callback (jack_client_t *client, - JackSampleRateCallback srate_callback, - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the JACK server to call @a client_registration_callback whenever a - * client is registered or unregistered, passing @a arg as a parameter. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_client_registration_callback (jack_client_t *client, - JackClientRegistrationCallback - registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the JACK server to call @a registration_callback whenever a - * port is registered or unregistered, passing @a arg as a parameter. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code - */ - int jack_set_port_registration_callback (jack_client_t *client, - JackPortRegistrationCallback - registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - - /** - * Tell the JACK server to call @a connect_callback whenever a - * port is connected or disconnected, passing @a arg as a parameter. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_port_connect_callback (jack_client_t *client, - JackPortConnectCallback - connect_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - - /** - * Tell the JACK server to call @a rename_callback whenever a - * port is renamed, passing @a arg as a parameter. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_port_rename_callback (jack_client_t *client, - JackPortRenameCallback - rename_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the JACK server to call @a graph_callback whenever the - * processing graph is reordered, passing @a arg as a parameter. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_graph_order_callback (jack_client_t *client, - JackGraphOrderCallback graph_callback, - void *) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Tell the JACK server to call @a xrun_callback whenever there is a - * xrun, passing @a arg as a parameter. - * - * All "notification events" are received in a seperated non RT thread, - * the code in the supplied function does not need to be - * suitable for real-time execution. - * - * NOTE: this function cannot be called while the client is activated - * (after jack_activate has been called.) - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_xrun_callback (jack_client_t *client, - JackXRunCallback xrun_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -/** - * Tell the Jack server to call @a latency_callback whenever it - * is necessary to recompute the latencies for some or all - * Jack ports. - * - * @a latency_callback will be called twice each time it is - * needed, once being passed JackCaptureLatency and once - * JackPlaybackLatency. See @ref LatencyFunctions for - * the definition of each type of latency and related functions. - * - * IMPORTANT: Most JACK clients do NOT need to register a latency - * callback. - * - * Clients that meet any of the following conditions do NOT - * need to register a latency callback: - * - * - have only input ports - * - have only output ports - * - their output is totally unrelated to their input - * - their output is not delayed relative to their input - * (i.e. data that arrives in a given process() - * callback is processed and output again in the - * same callback) - * - * Clients NOT registering a latency callback MUST also - * satisfy this condition: - * - * - have no multiple distinct internal signal pathways - * - * This means that if your client has more than 1 input and - * output port, and considers them always "correlated" - * (e.g. as a stereo pair), then there is only 1 (e.g. stereo) - * signal pathway through the client. This would be true, - * for example, of a stereo FX rack client that has a - * left/right input pair and a left/right output pair. - * - * However, this is somewhat a matter of perspective. The - * same FX rack client could be connected so that its - * two input ports were connected to entirely separate - * sources. Under these conditions, the fact that the client - * does not register a latency callback MAY result - * in port latency values being incorrect. - * - * Clients that do not meet any of those conditions SHOULD - * register a latency callback. - * - * See the documentation for @ref jack_port_set_latency_range() - * on how the callback should operate. Remember that the @a mode - * argument given to the latency callback will need to be - * passed into @ref jack_port_set_latency_range() - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_latency_callback (jack_client_t *client, - JackLatencyCallback latency_callback, - void *) JACK_WEAK_EXPORT; -/*@}*/ - -/** - * @defgroup ServerClientControl Controlling & querying JACK server operation - * @{ - */ - -/** - * Start/Stop JACK's "freewheel" mode. - * - * When in "freewheel" mode, JACK no longer waits for - * any external event to begin the start of the next process - * cycle. - * - * As a result, freewheel mode causes "faster than realtime" - * execution of a JACK graph. If possessed, real-time - * scheduling is dropped when entering freewheel mode, and - * if appropriate it is reacquired when stopping. - * - * IMPORTANT: on systems using capabilities to provide real-time - * scheduling (i.e. Linux kernel 2.4), if onoff is zero, this function - * must be called from the thread that originally called jack_activate(). - * This restriction does not apply to other systems (e.g. Linux kernel 2.6 - * or OS X). - * - * @param client pointer to JACK client structure - * @param onoff if non-zero, freewheel mode starts. Otherwise - * freewheel mode ends. - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_set_freewheel(jack_client_t* client, int onoff) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Change the buffer size passed to the @a process_callback. - * - * This operation stops the JACK engine process cycle, then calls all - * registered @a bufsize_callback functions before restarting the - * process cycle. This will cause a gap in the audio flow, so it - * should only be done at appropriate stopping points. - * - * @see jack_set_buffer_size_callback() - * - * @param client pointer to JACK client structure. - * @param nframes new buffer size. Must be a power of two. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the sample rate of the jack system, as set by the user when - * jackd was started. - */ -jack_nframes_t jack_get_sample_rate (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the current maximum size that will ever be passed to the @a - * process_callback. It should only be used *before* the client has - * been activated. This size may change, clients that depend on it - * must register a @a bufsize_callback so they will be notified if it - * does. - * - * @see jack_set_buffer_size_callback() - */ -jack_nframes_t jack_get_buffer_size (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Old-style interface to become the timebase for the entire JACK - * subsystem. - * - * @deprecated This function still exists for compatibility with the - * earlier transport interface, but it does nothing. Instead, see - * transport.h and use jack_set_timebase_callback(). - * - * @return ENOSYS, function not implemented. - */ -int jack_engine_takeover_timebase (jack_client_t *) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * @return the current CPU load estimated by JACK. This is a running - * average of the time it takes to execute a full process cycle for - * all clients as a percentage of the real time available per cycle - * determined by the buffer size and sample rate. - */ -float jack_cpu_load (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -/** - * @defgroup PortFunctions Creating & manipulating ports - * @{ - */ - -/** - * Create a new port for the client. This is an object used for moving - * data of any type in or out of the client. Ports may be connected - * in various ways. - * - * Each port has a short name. The port's full name contains the name - * of the client concatenated with a colon (:) followed by its short - * name. The jack_port_name_size() is the maximum length of this full - * name. Exceeding that will cause the port registration to fail and - * return NULL. - * - * The @a port_name must be unique among all ports owned by this client. - * If the name is not unique, the registration will fail. - * - * All ports have a type, which may be any non-NULL and non-zero - * length string, passed as an argument. Some port types are built - * into the JACK API, currently only JACK_DEFAULT_AUDIO_TYPE. - * - * @param client pointer to JACK client structure. - * @param port_name non-empty short name for the new port (not - * including the leading @a "client_name:"). Must be unique. - * @param port_type port type name. If longer than - * jack_port_type_size(), only that many characters are significant. - * @param flags @ref JackPortFlags bit mask. - * @param buffer_size must be non-zero if this is not a built-in @a - * port_type. Otherwise, it is ignored. - * - * @return jack_port_t pointer on success, otherwise NULL. - */ -jack_port_t * jack_port_register (jack_client_t *client, - const char *port_name, - const char *port_type, - unsigned long flags, - unsigned long buffer_size) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Remove the port from the client, disconnecting any existing - * connections. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_port_unregister (jack_client_t *client, jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * This returns a pointer to the memory area associated with the - * specified port. For an output port, it will be a memory area - * that can be written to; for an input port, it will be an area - * containing the data from the port's connection(s), or - * zero-filled. if there are multiple inbound connections, the data - * will be mixed appropriately. - * - * FOR OUTPUT PORTS ONLY : DEPRECATED in Jack 2.0 !! - * --------------------------------------------------- - * You may cache the value returned, but only between calls to - * your "blocksize" callback. For this reason alone, you should - * either never cache the return value or ensure you have - * a "blocksize" callback and be sure to invalidate the cached - * address from there. - * - * Caching output ports is DEPRECATED in Jack 2.0, due to some new optimization (like "pipelining"). - * Port buffers have to be retrieved in each callback for proper functionning. - */ -void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the UUID of the jack_port_t - * - * @see jack_uuid_to_string() to convert into a string representation - */ -jack_uuid_t jack_port_uuid (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the full name of the jack_port_t (including the @a - * "client_name:" prefix). - * - * @see jack_port_name_size(). - */ -const char * jack_port_name (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the short name of the jack_port_t (not including the @a - * "client_name:" prefix). - * - * @see jack_port_name_size(). - */ -const char * jack_port_short_name (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the @ref JackPortFlags of the jack_port_t. - */ -int jack_port_flags (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the @a port type, at most jack_port_type_size() characters - * including a final NULL. - */ -const char * jack_port_type (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - - /** - * @return the @a port type id. - */ -jack_port_type_id_t jack_port_type_id (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return TRUE if the jack_port_t belongs to the jack_client_t. - */ -int jack_port_is_mine (const jack_client_t *client, const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return number of connections to or from @a port. - * - * @pre The calling client must own @a port. - */ -int jack_port_connected (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return TRUE if the locally-owned @a port is @b directly connected - * to the @a port_name. - * - * @see jack_port_name_size() - */ -int jack_port_connected_to (const jack_port_t *port, - const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return a null-terminated array of full port names to which the @a - * port is connected. If none, returns NULL. - * - * The caller is responsible for calling jack_free() on any non-NULL - * returned value. - * - * @param port locally owned jack_port_t pointer. - * - * @see jack_port_name_size(), jack_port_get_all_connections() - */ -const char ** jack_port_get_connections (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return a null-terminated array of full port names to which the @a - * port is connected. If none, returns NULL. - * - * The caller is responsible for calling jack_free() on any non-NULL - * returned value. - * - * This differs from jack_port_get_connections() in two important - * respects: - * - * 1) You may not call this function from code that is - * executed in response to a JACK event. For example, - * you cannot use it in a GraphReordered handler. - * - * 2) You need not be the owner of the port to get information - * about its connections. - * - * @see jack_port_name_size() - */ -const char ** jack_port_get_all_connections (const jack_client_t *client, - const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * - * @deprecated This function will be removed from a future version - * of JACK. Do not use it. There is no replacement. It has - * turned out to serve essentially no purpose in real-life - * JACK clients. - */ -int jack_port_tie (jack_port_t *src, jack_port_t *dst) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * - * @deprecated This function will be removed from a future version - * of JACK. Do not use it. There is no replacement. It has - * turned out to serve essentially no purpose in real-life - * JACK clients. - */ -int jack_port_untie (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * \bold THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN - * NEW JACK CLIENTS - * - * Modify a port's short name. May be called at any time. If the - * resulting full name (including the @a "client_name:" prefix) is - * longer than jack_port_name_size(), it will be truncated. - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_port_set_name (jack_port_t *port, const char *port_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * Modify a port's short name. May NOT be called from a callback handling a server event. - * If the resulting full name (including the @a "client_name:" prefix) is - * longer than jack_port_name_size(), it will be truncated. - * - * @return 0 on success, otherwise a non-zero error code. - * - * This differs from jack_port_set_name() by triggering PortRename notifications to - * clients that have registered a port rename handler. - */ -int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Set @a alias as an alias for @a port. May be called at any time. - * If the alias is longer than jack_port_name_size(), it will be truncated. - * - * After a successful call, and until JACK exits or - * @function jack_port_unset_alias() is called, @alias may be - * used as a alternate name for the port. - * - * Ports can have up to two aliases - if both are already - * set, this function will return an error. - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_port_set_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Remove @a alias as an alias for @a port. May be called at any time. - * - * After a successful call, @a alias can no longer be - * used as a alternate name for the port. - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_port_unset_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Get any aliases known for @port. - * - * @return the number of aliases discovered for the port - */ -int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2]) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * If @ref JackPortCanMonitor is set for this @a port, turn input - * monitoring on or off. Otherwise, do nothing. - */ -int jack_port_request_monitor (jack_port_t *port, int onoff) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * If @ref JackPortCanMonitor is set for this @a port_name, turn input - * monitoring on or off. Otherwise, do nothing. - * - * @return 0 on success, otherwise a non-zero error code. - * - * @see jack_port_name_size() - */ -int jack_port_request_monitor_by_name (jack_client_t *client, - const char *port_name, int onoff) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * If @ref JackPortCanMonitor is set for a port, this function turns - * on input monitoring if it was off, and turns it off if only one - * request has been made to turn it on. Otherwise it does nothing. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_port_ensure_monitor (jack_port_t *port, int onoff) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return TRUE if input monitoring has been requested for @a port. - */ -int jack_port_monitoring_input (jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Establish a connection between two ports. - * - * When a connection exists, data written to the source port will - * be available to be read at the destination port. - * - * @pre The port types must be identical. - * - * @pre The @ref JackPortFlags of the @a source_port must include @ref - * JackPortIsOutput. - * - * @pre The @ref JackPortFlags of the @a destination_port must include - * @ref JackPortIsInput. - * - * @return 0 on success, EEXIST if the connection is already made, - * otherwise a non-zero error code - */ -int jack_connect (jack_client_t *client, - const char *source_port, - const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Remove a connection between two ports. - * - * @pre The port types must be identical. - * - * @pre The @ref JackPortFlags of the @a source_port must include @ref - * JackPortIsOutput. - * - * @pre The @ref JackPortFlags of the @a destination_port must include - * @ref JackPortIsInput. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_disconnect (jack_client_t *client, - const char *source_port, - const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Perform the same function as jack_disconnect() using port handles - * rather than names. This avoids the name lookup inherent in the - * name-based version. - * - * Clients connecting their own ports are likely to use this function, - * while generic connection clients (e.g. patchbays) would use - * jack_disconnect(). - */ -int jack_port_disconnect (jack_client_t *client, jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the maximum number of characters in a full JACK port name - * including the final NULL character. This value is a constant. - * - * A port's full name contains the owning client name concatenated - * with a colon (:) followed by its short name and a NULL - * character. - */ -int jack_port_name_size(void) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the maximum number of characters in a JACK port type name - * including the final NULL character. This value is a constant. - */ -int jack_port_type_size(void) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the buffersize of a port of type @arg port_type. - * - * this function may only be called in a buffer_size callback. - */ -size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_type) JACK_WEAK_EXPORT; - -/*@}*/ - -/** - * @defgroup LatencyFunctions Managing and determining latency - * - * The purpose of JACK's latency API is to allow clients to - * easily answer two questions: - * - * - How long has it been since the data read from a port arrived - * at the edge of the JACK graph (either via a physical port - * or being synthesized from scratch)? - * - * - How long will it be before the data written to a port arrives - * at the edge of a JACK graph? - - * To help answering these two questions, all JACK ports have two - * latency values associated with them, both measured in frames: - * - * capture latency: how long since the data read from - * the buffer of a port arrived at - * a port marked with JackPortIsTerminal. - * The data will have come from the "outside - * world" if the terminal port is also - * marked with JackPortIsPhysical, or - * will have been synthesized by the client - * that owns the terminal port. - * - * playback latency: how long until the data - * written to the buffer of port will reach a port - * marked with JackPortIsTerminal. - * - * Both latencies might potentially have more than one value - * because there may be multiple pathways to/from a given port - * and a terminal port. Latency is therefore generally - * expressed a min/max pair. - * - * In most common setups, the minimum and maximum latency - * are the same, but this design accomodates more complex - * routing, and allows applications (and thus users) to - * detect cases where routing is creating an anomalous - * situation that may either need fixing or more - * sophisticated handling by clients that care about - * latency. - * - * See also @ref jack_set_latency_callback for details on how - * clients that add latency to the signal path should interact - * with JACK to ensure that the correct latency figures are - * used. - * @{ - */ - -/** - * The port latency is zero by default. Clients that control - * physical hardware with non-zero latency should call this - * to set the latency to its correct value. Note that the value - * should include any systemic latency present "outside" the - * physical hardware controlled by the client. For example, - * for a client controlling a digital audio interface connected - * to an external digital converter, the latency setting should - * include both buffering by the audio interface *and* the converter. - * - * @deprecated This method will be removed in the next major - * release of JACK. It should not be used in new code, and should - * be replaced by a latency callback that calls @ref - * jack_port_set_latency_range(). - */ -void jack_port_set_latency (jack_port_t *port, jack_nframes_t) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * return the latency range defined by @a mode for - * @a port, in frames. - * - * See @ref LatencyFunctions for the definition of each latency value. - * - * This is normally used in the LatencyCallback. - * and therefor safe to execute from callbacks. - */ -void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; - -/** - * set the minimum and maximum latencies defined by - * @a mode for @a port, in frames. - * - * See @ref LatencyFunctions for the definition of each latency value. - * - * This function should ONLY be used inside a latency - * callback. The client should determine the current - * value of the latency using @ref jack_port_get_latency_range() - * (called using the same mode as @a mode) - * and then add some number of frames to that reflects - * latency added by the client. - * - * How much latency a client adds will vary - * dramatically. For most clients, the answer is zero - * and there is no reason for them to register a latency - * callback and thus they should never call this - * function. - * - * More complex clients that take an input signal, - * transform it in some way and output the result but - * not during the same process() callback will - * generally know a single constant value to add - * to the value returned by @ref jack_port_get_latency_range(). - * - * Such clients would register a latency callback (see - * @ref jack_set_latency_callback) and must know what input - * ports feed which output ports as part of their - * internal state. Their latency callback will update - * the ports' latency values appropriately. - * - * A pseudo-code example will help. The @a mode argument to the latency - * callback will determine whether playback or capture - * latency is being set. The callback will use - * @ref jack_port_set_latency_range() as follows: - * - * \code - * jack_latency_range_t range; - * if (mode == JackPlaybackLatency) { - * foreach input_port in (all self-registered port) { - * jack_port_get_latency_range (port_feeding_input_port, JackPlaybackLatency, &range); - * range.min += min_delay_added_as_signal_flows_from port_feeding to input_port; - * range.max += max_delay_added_as_signal_flows_from port_feeding to input_port; - * jack_port_set_latency_range (input_port, JackPlaybackLatency, &range); - * } - * } else if (mode == JackCaptureLatency) { - * foreach output_port in (all self-registered port) { - * jack_port_get_latency_range (port_fed_by_output_port, JackCaptureLatency, &range); - * range.min += min_delay_added_as_signal_flows_from_output_port_to_fed_by_port; - * range.max += max_delay_added_as_signal_flows_from_output_port_to_fed_by_port; - * jack_port_set_latency_range (output_port, JackCaptureLatency, &range); - * } - * } - * \endcode - * - * In this relatively simple pseudo-code example, it is assumed that - * each input port or output is connected to only 1 output or input - * port respectively. - * - * If a port is connected to more than 1 other port, then the - * range.min and range.max values passed to @ref - * jack_port_set_latency_range() should reflect the minimum and - * maximum values across all connected ports. - * - * See the description of @ref jack_set_latency_callback for more - * information. - */ -void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; - -/** - * Request a complete recomputation of all port latencies. This - * can be called by a client that has just changed the internal - * latency of its port using jack_port_set_latency - * and wants to ensure that all signal pathways in the graph - * are updated with respect to the values that will be returned - * by jack_port_get_total_latency. It allows a client - * to change multiple port latencies without triggering a - * recompute for each change. - * - * @return zero for successful execution of the request. non-zero - * otherwise. - */ -int jack_recompute_total_latencies (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the time (in frames) between data being available or - * delivered at/to a port, and the time at which it arrived at or is - * delivered to the "other side" of the port. E.g. for a physical - * audio output port, this is the time between writing to the port and - * when the signal will leave the connector. For a physical audio - * input port, this is the time between the sound arriving at the - * connector and the corresponding frames being readable from the - * port. - * - * @deprecated This method will be removed in the next major - * release of JACK. It should not be used in new code, and should - * be replaced by jack_port_get_latency_range() in any existing - * use cases. - */ -jack_nframes_t jack_port_get_latency (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * The maximum of the sum of the latencies in every - * connection path that can be drawn between the port and other - * ports with the @ref JackPortIsTerminal flag set. - * - * @deprecated This method will be removed in the next major - * release of JACK. It should not be used in new code, and should - * be replaced by jack_port_get_latency_range() in any existing - * use cases. - */ -jack_nframes_t jack_port_get_total_latency (jack_client_t *client, - jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/** - * Request a complete recomputation of a port's total latency. This - * can be called by a client that has just changed the internal - * latency of its port using jack_port_set_latency - * and wants to ensure that all signal pathways in the graph - * are updated with respect to the values that will be returned - * by jack_port_get_total_latency. - * - * @return zero for successful execution of the request. non-zero - * otherwise. - * - * @deprecated This method will be removed in the next major - * release of JACK. It should not be used in new code, and should - * be replaced by jack_recompute_total_latencies() in any existing - * use cases. - */ -int jack_recompute_total_latency (jack_client_t*, jack_port_t* port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; - -/*@}*/ - -/** - * @defgroup PortSearching Looking up ports - * @{ - */ - -/** - * @param port_name_pattern A regular expression used to select - * ports by name. If NULL or of zero length, no selection based - * on name will be carried out. - * @param type_name_pattern A regular expression used to select - * ports by type. If NULL or of zero length, no selection based - * on type will be carried out. - * @param flags A value used to select ports by their flags. - * If zero, no selection based on flags will be carried out. - * - * @return a NULL-terminated array of ports that match the specified - * arguments. The caller is responsible for calling jack_free() any - * non-NULL returned value. - * - * @see jack_port_name_size(), jack_port_type_size() - */ -const char ** jack_get_ports (jack_client_t *client, - const char *port_name_pattern, - const char *type_name_pattern, - unsigned long flags) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return address of the jack_port_t named @a port_name. - * - * @see jack_port_name_size() - */ -jack_port_t * jack_port_by_name (jack_client_t *client, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return address of the jack_port_t of a @a port_id. - */ -jack_port_t * jack_port_by_id (jack_client_t *client, - jack_port_id_t port_id) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -/** - * @defgroup TimeFunctions Handling time - * @{ - * - * JACK time is in units of 'frames', according to the current sample rate. - * The absolute value of frame times is meaningless, frame times have meaning - * only relative to each other. - */ - -/** - * @return the estimated time in frames that has passed since the JACK - * server began the current process cycle. - */ -jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the estimated current time in frames. - * This function is intended for use in other threads (not the process - * callback). The return value can be compared with the value of - * jack_last_frame_time to relate time in other threads to JACK time. - */ -jack_nframes_t jack_frame_time (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the precise time at the start of the current process cycle. - * This function may only be used from the process callback, and can - * be used to interpret timestamps generated by jack_frame_time() in - * other threads with respect to the current process cycle. - * - * This is the only jack time function that returns exact time: - * when used during the process callback it always returns the same - * value (until the next process callback, where it will return - * that value + nframes, etc). The return value is guaranteed to be - * monotonic and linear in this fashion unless an xrun occurs. - * If an xrun occurs, clients must check this value again, as time - * may have advanced in a non-linear way (e.g. cycles may have been skipped). - */ -jack_nframes_t jack_last_frame_time (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * This function may only be used from the process callback. - * It provides the internal cycle timing information as used by - * most of the other time related functions. This allows the - * caller to map between frame counts and microseconds with full - * precision (i.e. without rounding frame times to integers), - * and also provides e.g. the microseconds time of the start of - * the current cycle directly (it has to be computed otherwise). - * - * If the return value is zero, the following information is - * provided in the variables pointed to by the arguments: - * - * current_frames: the frame time counter at the start of the - * current cycle, same as jack_last_frame_time(). - * current_usecs: the microseconds time at the start of the - * current cycle. - * next_usecs: the microseconds time of the start of the next - * next cycle as computed by the DLL. - * period_usecs: the current best estimate of the period time in - * microseconds. - * - * NOTES: - * - * Because of the types used, all the returned values except period_usecs - * are unsigned. In computations mapping between frames and microseconds - * *signed* differences are required. The easiest way is to compute those - * separately and assign them to the appropriate signed variables, - * int32_t for frames and int64_t for usecs. See the implementation of - * jack_frames_to_time() and Jack_time_to_frames() for an example. - * - * Unless there was an xrun, skipped cycles, or the current cycle is the - * first after freewheeling or starting Jack, the value of current_usecs - * will always be the value of next_usecs of the previous cycle. - * - * The value of period_usecs will in general NOT be exactly equal to - * the difference of next_usecs and current_usecs. This is because to - * ensure stability of the DLL and continuity of the mapping, a fraction - * of the loop error must be included in next_usecs. For an accurate - * mapping between frames and microseconds, the difference of next_usecs - * and current_usecs should be used, and not period_usecs. - * - * @return zero if OK, non-zero otherwise. - */ -int jack_get_cycle_times(const jack_client_t *client, - jack_nframes_t *current_frames, - jack_time_t *current_usecs, - jack_time_t *next_usecs, - float *period_usecs) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the estimated time in microseconds of the specified frame time - */ -jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return the estimated time in frames for the specified system time. - */ -jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @return return JACK's current system time in microseconds, - * using the JACK clock source. - * - * The value returned is guaranteed to be monotonic, but not linear. - */ -jack_time_t jack_get_time(void) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -/** - * @defgroup ErrorOutput Controlling error/information output - */ -/*@{*/ - -/** - * Display JACK error message. - * - * Set via jack_set_error_function(), otherwise a JACK-provided - * default will print @a msg (plus a newline) to stderr. - * - * @param msg error message text (no newline at end). - */ -extern void (*jack_error_callback)(const char *msg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Set the @ref jack_error_callback for error message display. - * Set it to NULL to restore default_jack_error_callback function. - * - * The JACK library provides two built-in callbacks for this purpose: - * default_jack_error_callback() and silent_jack_error_callback(). - */ -void jack_set_error_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Display JACK info message. - * - * Set via jack_set_info_function(), otherwise a JACK-provided - * default will print @a msg (plus a newline) to stdout. - * - * @param msg info message text (no newline at end). - */ -extern void (*jack_info_callback)(const char *msg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Set the @ref jack_info_callback for info message display. - * Set it to NULL to restore default_jack_info_callback function. - * - * The JACK library provides two built-in callbacks for this purpose: - * default_jack_info_callback() and silent_jack_info_callback(). - */ -void jack_set_info_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -/** - * The free function to be used on memory returned by jack_port_get_connections, - * jack_port_get_all_connections, jack_get_ports and jack_get_internal_client_name functions. - * This is MANDATORY on Windows when otherwise all nasty runtime version related crashes can occur. - * Developers are strongly encouraged to use this function instead of the standard "free" function in new code. - * - * @param ptr the memory pointer to be deallocated. - */ -void jack_free(void* ptr) JACK_OPTIONAL_WEAK_EXPORT; - - -#ifdef __cplusplus -} -#endif - -#endif /* __jack_h__ */ diff --git a/extern/include/jack/jslist.h b/extern/include/jack/jslist.h deleted file mode 100644 index 3ec0ce92..00000000 --- a/extern/include/jack/jslist.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - Based on gslist.c from glib-1.2.9 (LGPL). - - Adaption to JACK, Copyright (C) 2002 Kai Vehmanen. - - replaced use of gtypes with normal ANSI C types - - glib's memory allocation routines replaced with - malloc/free calls - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __jack_jslist_h__ -#define __jack_jslist_h__ - -#include -#include - -#ifdef sun -#define __inline__ -#endif - -typedef struct _JSList JSList; - -typedef int (*JCompareFunc) (void* a, void* b); -struct _JSList -{ - void *data; - JSList *next; -}; - -static __inline__ -JSList* -jack_slist_alloc (void) -{ - JSList *new_list; - - new_list = (JSList*)malloc(sizeof(JSList)); - if (new_list) { - new_list->data = NULL; - new_list->next = NULL; - } - - return new_list; -} - -static __inline__ -JSList* -jack_slist_prepend (JSList* list, void* data) -{ - JSList *new_list; - - new_list = (JSList*)malloc(sizeof(JSList)); - if (new_list) { - new_list->data = data; - new_list->next = list; - } - - return new_list; -} - -#define jack_slist_next(slist) ((slist) ? (((JSList *)(slist))->next) : NULL) -static __inline__ -JSList* -jack_slist_last (JSList *list) -{ - if (list) { - while (list->next) - list = list->next; - } - - return list; -} - -static __inline__ -JSList* -jack_slist_remove_link (JSList *list, - JSList *link) -{ - JSList *tmp; - JSList *prev; - - prev = NULL; - tmp = list; - - while (tmp) { - if (tmp == link) { - if (prev) - prev->next = tmp->next; - if (list == tmp) - list = list->next; - - tmp->next = NULL; - break; - } - - prev = tmp; - tmp = tmp->next; - } - - return list; -} - -static __inline__ -void -jack_slist_free (JSList *list) -{ - while (list) { - JSList *next = list->next; - free(list); - list = next; - } -} - -static __inline__ -void -jack_slist_free_1 (JSList *list) -{ - if (list) { - free(list); - } -} - -static __inline__ -JSList* -jack_slist_remove (JSList *list, - void *data) -{ - JSList *tmp; - JSList *prev; - - prev = NULL; - tmp = list; - - while (tmp) { - if (tmp->data == data) { - if (prev) - prev->next = tmp->next; - if (list == tmp) - list = list->next; - - tmp->next = NULL; - jack_slist_free (tmp); - - break; - } - - prev = tmp; - tmp = tmp->next; - } - - return list; -} - -static __inline__ -unsigned int -jack_slist_length (JSList *list) -{ - unsigned int length; - - length = 0; - while (list) { - length++; - list = list->next; - } - - return length; -} - -static __inline__ -JSList* -jack_slist_find (JSList *list, - void *data) -{ - while (list) { - if (list->data == data) - break; - list = list->next; - } - - return list; -} - -static __inline__ -JSList* -jack_slist_copy (JSList *list) -{ - JSList *new_list = NULL; - - if (list) { - JSList *last; - - new_list = jack_slist_alloc (); - new_list->data = list->data; - last = new_list; - list = list->next; - while (list) { - last->next = jack_slist_alloc (); - last = last->next; - last->data = list->data; - list = list->next; - } - } - - return new_list; -} - -static __inline__ -JSList* -jack_slist_append (JSList *list, - void *data) -{ - JSList *new_list; - JSList *last; - - new_list = jack_slist_alloc (); - new_list->data = data; - - if (list) { - last = jack_slist_last (list); - last->next = new_list; - - return list; - } else - return new_list; -} - -static __inline__ -JSList* -jack_slist_sort_merge (JSList *l1, - JSList *l2, - JCompareFunc compare_func) -{ - JSList list, *l; - - l = &list; - - while (l1 && l2) { - if (compare_func(l1->data, l2->data) < 0) { - l = l->next = l1; - l1 = l1->next; - } else { - l = l->next = l2; - l2 = l2->next; - } - } - l->next = l1 ? l1 : l2; - - return list.next; -} - -static __inline__ -JSList* -jack_slist_sort (JSList *list, - JCompareFunc compare_func) -{ - JSList *l1, *l2; - - if (!list) - return NULL; - if (!list->next) - return list; - - l1 = list; - l2 = list->next; - - while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) - break; - l1 = l1->next; - } - l2 = l1->next; - l1->next = NULL; - - return jack_slist_sort_merge (jack_slist_sort (list, compare_func), - jack_slist_sort (l2, compare_func), - compare_func); -} - -#endif /* __jack_jslist_h__ */ - diff --git a/extern/include/jack/midiport.h b/extern/include/jack/midiport.h deleted file mode 100644 index 1a7d4e6d..00000000 --- a/extern/include/jack/midiport.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - Copyright (C) 2004 Ian Esten - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - - -#ifndef __JACK_MIDIPORT_H -#define __JACK_MIDIPORT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - - -/** Type for raw event data contained in @ref jack_midi_event_t. */ -typedef unsigned char jack_midi_data_t; - - -/** A Jack MIDI event. */ -typedef struct _jack_midi_event -{ - jack_nframes_t time; /**< Sample index at which event is valid */ - size_t size; /**< Number of bytes of data in \a buffer */ - jack_midi_data_t *buffer; /**< Raw MIDI data */ -} jack_midi_event_t; - - -/** - * @defgroup MIDIAPI Reading and writing MIDI data - * @{ - */ - -/** Get number of events in a port buffer. - * - * @param port_buffer Port buffer from which to retrieve event. - * @return number of events inside @a port_buffer - */ -uint32_t -jack_midi_get_event_count(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; - - -/** Get a MIDI event from an event port buffer. - * - * Jack MIDI is normalised, the MIDI event returned by this function is - * guaranteed to be a complete MIDI event (the status byte will always be - * present, and no realtime events will interspered with the event). - * - * @param event Event structure to store retrieved event in. - * @param port_buffer Port buffer from which to retrieve event. - * @param event_index Index of event to retrieve. - * @return 0 on success, ENODATA if buffer is empty. - */ -int -jack_midi_event_get(jack_midi_event_t *event, - void *port_buffer, - uint32_t event_index) JACK_OPTIONAL_WEAK_EXPORT; - - -/** Clear an event buffer. - * - * This should be called at the beginning of each process cycle before calling - * @ref jack_midi_event_reserve or @ref jack_midi_event_write. This - * function may not be called on an input port's buffer. - * - * @param port_buffer Port buffer to clear (must be an output port buffer). - */ -void -jack_midi_clear_buffer(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; - -/** Reset an event buffer (from data allocated outside of JACK). - * - * This should be called at the beginning of each process cycle before calling - * @ref jack_midi_event_reserve or @ref jack_midi_event_write. This - * function may not be called on an input port's buffer. - * - * @param port_buffer Port buffer to resetted. - */ -void -jack_midi_reset_buffer(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; - - -/** Get the size of the largest event that can be stored by the port. - * - * This function returns the current space available, taking into account - * events already stored in the port. - * - * @param port_buffer Port buffer to check size of. - */ -size_t -jack_midi_max_event_size(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; - - -/** Allocate space for an event to be written to an event port buffer. - * - * Clients are to write the actual event data to be written starting at the - * pointer returned by this function. Clients must not write more than - * @a data_size bytes into this buffer. Clients must write normalised - * MIDI data to the port - no running status and no (1-byte) realtime - * messages interspersed with other messages (realtime messages are fine - * when they occur on their own, like other messages). - * - * Events must be written in order, sorted by their sample offsets. - * JACK will not sort the events for you, and will refuse to store - * out-of-order events. - * - * @param port_buffer Buffer to write event to. - * @param time Sample offset of event. - * @param data_size Length of event's raw data in bytes. - * @return Pointer to the beginning of the reserved event's data buffer, or - * NULL on error (ie not enough space). - */ -jack_midi_data_t* -jack_midi_event_reserve(void *port_buffer, - jack_nframes_t time, - size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; - - -/** Write an event into an event port buffer. - * - * This function is simply a wrapper for @ref jack_midi_event_reserve - * which writes the event data into the space reserved in the buffer. - * - * Clients must not write more than - * @a data_size bytes into this buffer. Clients must write normalised - * MIDI data to the port - no running status and no (1-byte) realtime - * messages interspersed with other messages (realtime messages are fine - * when they occur on their own, like other messages). - * - * Events must be written in order, sorted by their sample offsets. - * JACK will not sort the events for you, and will refuse to store - * out-of-order events. - * - * @param port_buffer Buffer to write event to. - * @param time Sample offset of event. - * @param data Message data to be written. - * @param data_size Length of @a data in bytes. - * @return 0 on success, ENOBUFS if there's not enough space in buffer for event. - */ -int -jack_midi_event_write(void *port_buffer, - jack_nframes_t time, - const jack_midi_data_t *data, - size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; - - -/** Get the number of events that could not be written to @a port_buffer. - * - * This function returning a non-zero value implies @a port_buffer is full. - * Currently the only way this can happen is if events are lost on port mixdown. - * - * @param port_buffer Port to receive count for. - * @returns Number of events that could not be written to @a port_buffer. - */ -uint32_t -jack_midi_get_lost_event_count(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -#ifdef __cplusplus -} -#endif - - -#endif /* __JACK_MIDIPORT_H */ - - diff --git a/extern/include/jack/ringbuffer.h b/extern/include/jack/ringbuffer.h deleted file mode 100644 index cb0ca942..00000000 --- a/extern/include/jack/ringbuffer.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - Copyright (C) 2000 Paul Davis - Copyright (C) 2003 Rohan Drape - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef _RINGBUFFER_H -#define _RINGBUFFER_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include - -/** @file ringbuffer.h - * - * A set of library functions to make lock-free ringbuffers available - * to JACK clients. The `capture_client.c' (in the example_clients - * directory) is a fully functioning user of this API. - * - * The key attribute of a ringbuffer is that it can be safely accessed - * by two threads simultaneously -- one reading from the buffer and - * the other writing to it -- without using any synchronization or - * mutual exclusion primitives. For this to work correctly, there can - * only be a single reader and a single writer thread. Their - * identities cannot be interchanged. - */ - -typedef struct { - char *buf; - size_t len; -} -jack_ringbuffer_data_t ; - -typedef struct { - char *buf; - volatile size_t write_ptr; - volatile size_t read_ptr; - size_t size; - size_t size_mask; - int mlocked; -} -jack_ringbuffer_t ; - -/** - * Allocates a ringbuffer data structure of a specified size. The - * caller must arrange for a call to jack_ringbuffer_free() to release - * the memory associated with the ringbuffer. - * - * @param sz the ringbuffer size in bytes. - * - * @return a pointer to a new jack_ringbuffer_t, if successful; NULL - * otherwise. - */ -jack_ringbuffer_t *jack_ringbuffer_create(size_t sz); - -/** - * Frees the ringbuffer data structure allocated by an earlier call to - * jack_ringbuffer_create(). - * - * @param rb a pointer to the ringbuffer structure. - */ -void jack_ringbuffer_free(jack_ringbuffer_t *rb); - -/** - * Fill a data structure with a description of the current readable - * data held in the ringbuffer. This description is returned in a two - * element array of jack_ringbuffer_data_t. Two elements are needed - * because the data to be read may be split across the end of the - * ringbuffer. - * - * The first element will always contain a valid @a len field, which - * may be zero or greater. If the @a len field is non-zero, then data - * can be read in a contiguous fashion using the address given in the - * corresponding @a buf field. - * - * If the second element has a non-zero @a len field, then a second - * contiguous stretch of data can be read from the address given in - * its corresponding @a buf field. - * - * @param rb a pointer to the ringbuffer structure. - * @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. - * - */ -void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb, - jack_ringbuffer_data_t *vec); - -/** - * Fill a data structure with a description of the current writable - * space in the ringbuffer. The description is returned in a two - * element array of jack_ringbuffer_data_t. Two elements are needed - * because the space available for writing may be split across the end - * of the ringbuffer. - * - * The first element will always contain a valid @a len field, which - * may be zero or greater. If the @a len field is non-zero, then data - * can be written in a contiguous fashion using the address given in - * the corresponding @a buf field. - * - * If the second element has a non-zero @a len field, then a second - * contiguous stretch of data can be written to the address given in - * the corresponding @a buf field. - * - * @param rb a pointer to the ringbuffer structure. - * @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. - */ -void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb, - jack_ringbuffer_data_t *vec); - -/** - * Read data from the ringbuffer. - * - * @param rb a pointer to the ringbuffer structure. - * @param dest a pointer to a buffer where data read from the - * ringbuffer will go. - * @param cnt the number of bytes to read. - * - * @return the number of bytes read, which may range from 0 to cnt. - */ -size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt); - -/** - * Read data from the ringbuffer. Opposed to jack_ringbuffer_read() - * this function does not move the read pointer. Thus it's - * a convenient way to inspect data in the ringbuffer in a - * continous fashion. The price is that the data is copied - * into a user provided buffer. For "raw" non-copy inspection - * of the data in the ringbuffer use jack_ringbuffer_get_read_vector(). - * - * @param rb a pointer to the ringbuffer structure. - * @param dest a pointer to a buffer where data read from the - * ringbuffer will go. - * @param cnt the number of bytes to read. - * - * @return the number of bytes read, which may range from 0 to cnt. - */ -size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt); - -/** - * Advance the read pointer. - * - * After data have been read from the ringbuffer using the pointers - * returned by jack_ringbuffer_get_read_vector(), use this function to - * advance the buffer pointers, making that space available for future - * write operations. - * - * @param rb a pointer to the ringbuffer structure. - * @param cnt the number of bytes read. - */ -void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt); - -/** - * Return the number of bytes available for reading. - * - * @param rb a pointer to the ringbuffer structure. - * - * @return the number of bytes available to read. - */ -size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb); - -/** - * Lock a ringbuffer data block into memory. - * - * Uses the mlock() system call. This is not a realtime operation. - * - * @param rb a pointer to the ringbuffer structure. - */ -int jack_ringbuffer_mlock(jack_ringbuffer_t *rb); - -/** - * Reset the read and write pointers, making an empty buffer. - * - * This is not thread safe. - * - * @param rb a pointer to the ringbuffer structure. - */ -void jack_ringbuffer_reset(jack_ringbuffer_t *rb); - -/** - * Reset the internal "available" size, and read and write pointers, making an empty buffer. - * - * This is not thread safe. - * - * @param rb a pointer to the ringbuffer structure. - * @param sz the new size, that must be less than allocated size. - */ -void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz); - -/** - * Write data into the ringbuffer. - * - * @param rb a pointer to the ringbuffer structure. - * @param src a pointer to the data to be written to the ringbuffer. - * @param cnt the number of bytes to write. - * - * @return the number of bytes write, which may range from 0 to cnt - */ -size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, - size_t cnt); - -/** - * Advance the write pointer. - * - * After data have been written the ringbuffer using the pointers - * returned by jack_ringbuffer_get_write_vector(), use this function - * to advance the buffer pointer, making the data available for future - * read operations. - * - * @param rb a pointer to the ringbuffer structure. - * @param cnt the number of bytes written. - */ -void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt); - -/** - * Return the number of bytes available for writing. - * - * @param rb a pointer to the ringbuffer structure. - * - * @return the amount of free space (in bytes) available for writing. - */ -size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/extern/include/jack/session.h b/extern/include/jack/session.h deleted file mode 100644 index 376e4433..00000000 --- a/extern/include/jack/session.h +++ /dev/null @@ -1,270 +0,0 @@ -/* - Copyright (C) 2001 Paul Davis - Copyright (C) 2004 Jack O'Quin - Copyright (C) 2010 Torben Hohn - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef __jack_session_h__ -#define __jack_session_h__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * @defgroup SessionClientFunctions Session API for clients. - * @{ - */ - - -/** - * Session event type. - * - * If a client cant save templates, i might just do a normal save. - * - * There is no "quit without saving" event because a client might refuse to - * quit when it has unsaved data, but other clients may have already quit. - * This results in too much confusion, so it is unsupported. - */ -enum JackSessionEventType { - /** - * Save the session completely. - * - * The client may save references to data outside the provided directory, - * but it must do so by creating a link inside the provided directory and - * referring to that in any save files. The client must not refer to data - * files outside the provided directory directly in save files, because - * this makes it impossible for the session manager to create a session - * archive for distribution or archival. - */ - JackSessionSave = 1, - - /** - * Save the session completly, then quit. - * - * The rules for saving are exactly the same as for JackSessionSave. - */ - JackSessionSaveAndQuit = 2, - - /** - * Save a session template. - * - * A session template is a "skeleton" of the session, but without any data. - * Clients must save a session that, when restored, will create the same - * ports as a full save would have. However, the actual data contained in - * the session may not be saved (e.g. a DAW would create the necessary - * tracks, but not save the actual recorded data). - */ - JackSessionSaveTemplate = 3 -}; - -typedef enum JackSessionEventType jack_session_event_type_t; - -/** - * @ref jack_session_flags_t bits - */ -enum JackSessionFlags { - /** - * An error occured while saving. - */ - JackSessionSaveError = 0x01, - - /** - * Client needs to be run in a terminal. - */ - JackSessionNeedTerminal = 0x02 -}; - -/** - * Session flags. - */ -typedef enum JackSessionFlags jack_session_flags_t; - -struct _jack_session_event { - /** - * The type of this session event. - */ - jack_session_event_type_t type; - - /** - * Session directory path, with trailing separator. - * - * This directory is exclusive to the client; when saving the client may - * create any files it likes in this directory. - */ - const char *session_dir; - - /** - * Client UUID which must be passed to jack_client_open on session load. - * - * The client can specify this in the returned command line, or save it - * in a state file within the session directory. - */ - const char *client_uuid; - - /** - * Reply (set by client): the command line needed to restore the client. - * - * This is a platform dependent command line. It must contain - * ${SESSION_DIR} instead of the actual session directory path. More - * generally, just as in session files, clients should not include any - * paths outside the session directory here as this makes - * archival/distribution impossible. - * - * This field is set to NULL by Jack when the event is delivered to the - * client. The client must set to allocated memory that is safe to - * free(). This memory will be freed by jack_session_event_free. - */ - char *command_line; - - /** - * Reply (set by client): Session flags. - */ - jack_session_flags_t flags; - - /** - * Future flags. Set to zero for now. - */ - uint32_t future; -}; - -typedef struct _jack_session_event jack_session_event_t; - -/** - * Prototype for the client supplied function that is called - * whenever a session notification is sent via jack_session_notify(). - * - * Ownership of the memory of @a event is passed to the application. - * It must be freed using jack_session_event_free when its not used anymore. - * - * The client must promptly call jack_session_reply for this event. - * - * @param event The event structure. - * @param arg Pointer to a client supplied structure. - */ -typedef void (*JackSessionCallback)(jack_session_event_t *event, - void *arg); - -/** - * Tell the JACK server to call @a session_callback when a session event - * is to be delivered. - * - * setting more than one session_callback per process is probably a design - * error. if you have a multiclient application its more sensible to create - * a jack_client with only a session callback set. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_set_session_callback (jack_client_t *client, - JackSessionCallback session_callback, - void *arg) JACK_WEAK_EXPORT; - -/** - * Reply to a session event. - * - * This can either be called directly from the callback, or later from a - * different thread. For example, it is possible to push the event through a - * queue and execute the save code from the GUI thread. - * - * @return 0 on success, otherwise a non-zero error code - */ -int jack_session_reply (jack_client_t *client, - jack_session_event_t *event) JACK_WEAK_EXPORT; - - -/** - * Free memory used by a jack_session_event_t. - * - * This also frees the memory used by the command_line pointer, if its non NULL. - */ -void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT; - - -/** - * Get the assigned uuid for client. - * Safe to call from callback and all other threads. - * - * The caller is responsible for calling jack_free(3) on any non-NULL - * returned value. - */ -char *jack_client_get_uuid (jack_client_t *client) JACK_WEAK_EXPORT; - -/** - * @} - */ - -/** - * @defgroup JackSessionManagerAPI API for a session manager. - * - * @{ - */ - -typedef struct { - const char *uuid; - const char *client_name; - const char *command; - jack_session_flags_t flags; -} jack_session_command_t; - -/** - * Send an event to all clients listening for session callbacks. - * - * The returned strings of the clients are accumulated and returned as an array - * of jack_session_command_t. its terminated by ret[i].uuid == NULL target == - * NULL means send to all interested clients. otherwise a clientname - */ -jack_session_command_t *jack_session_notify ( - jack_client_t* client, - const char *target, - jack_session_event_type_t type, - const char *path) JACK_WEAK_EXPORT; - -/** - * Free the memory allocated by a session command. - */ -void jack_session_commands_free (jack_session_command_t *cmds) JACK_WEAK_EXPORT; - -/** - * Reserve a client name and associate it with a UUID. - * - * When a client later calls jack_client_open() and specifies the UUID, jackd - * will assign the reserved name. This allows a session manager to know in - * advance under which client name its managed clients will appear. - * - * @return 0 on success, otherwise a non-zero error code - */ -int -jack_reserve_client_name (jack_client_t *client, - const char *name, - const char *uuid) JACK_WEAK_EXPORT; - -/** - * Find out whether a client has set up a session callback. - * - * @return 0 when the client has no session callback, 1 when it has one. - * -1 on error. - */ -int -jack_client_has_session_callback (jack_client_t *client, const char *client_name) JACK_WEAK_EXPORT; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/extern/include/jack/statistics.h b/extern/include/jack/statistics.h deleted file mode 100644 index 28c270d0..00000000 --- a/extern/include/jack/statistics.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (C) 2004 Rui Nuno Capela, Lee Revell -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public License -* as published by the Free Software Foundation; either version 2.1 -* 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 -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this program; if not, write to the Free -* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -* 02111-1307, USA. -* -*/ - -#ifndef __statistics_h__ -#define __statistics_h__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include - -/** - * @return the maximum delay reported by the backend since - * startup or reset. When compared to the period size in usecs, this - * can be used to estimate the ideal period size for a given setup. - */ -float jack_get_max_delayed_usecs (jack_client_t *client); - -/** - * @return the delay in microseconds due to the most recent XRUN - * occurrence. This probably only makes sense when called from a @ref - * JackXRunCallback defined using jack_set_xrun_callback(). - */ -float jack_get_xrun_delayed_usecs (jack_client_t *client); - -/** - * Reset the maximum delay counter. This would be useful - * to estimate the effect that a change to the configuration of a running - * system (e.g. toggling kernel preemption) has on the delay - * experienced by JACK, without having to restart the JACK engine. - */ -void jack_reset_max_delayed_usecs (jack_client_t *client); - -#ifdef __cplusplus -} -#endif - -#endif /* __statistics_h__ */ diff --git a/extern/include/jack/systemdeps.h b/extern/include/jack/systemdeps.h deleted file mode 100644 index 7bec7152..00000000 --- a/extern/include/jack/systemdeps.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright (C) 2004-2012 Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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. - -*/ - -#ifndef __jack_systemdeps_h__ -#define __jack_systemdeps_h__ - -#ifndef POST_PACKED_STRUCTURE - - #ifdef __GNUC__ - /* POST_PACKED_STRUCTURE needs to be a macro which - expands into a compiler directive. The directive must - tell the compiler to arrange the preceding structure - declaration so that it is packed on byte-boundaries rather - than use the natural alignment of the processor and/or - compiler. - */ - - #define PRE_PACKED_STRUCTURE - #define POST_PACKED_STRUCTURE __attribute__((__packed__)) - - #else - - #ifdef _MSC_VER - #define PRE_PACKED_STRUCTURE1 __pragma(pack(push,1)) - #define PRE_PACKED_STRUCTURE PRE_PACKED_STRUCTURE1 - /* PRE_PACKED_STRUCTURE needs to be a macro which - expands into a compiler directive. The directive must - tell the compiler to arrange the following structure - declaration so that it is packed on byte-boundaries rather - than use the natural alignment of the processor and/or - compiler. - */ - #define POST_PACKED_STRUCTURE ;__pragma(pack(pop)) - /* and POST_PACKED_STRUCTURE needs to be a macro which - restores the packing to its previous setting */ - #else - #define PRE_PACKED_STRUCTURE - #define POST_PACKED_STRUCTURE - #endif /* _MSC_VER */ - - #endif /* __GNUC__ */ - -#endif - -#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(GNU_WIN32) - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #ifndef NOMINMAX - #define NOMINMAX - #endif - #include - - #ifdef _MSC_VER /* Microsoft compiler */ - #define __inline__ inline - #if (!defined(int8_t) && !defined(_STDINT)) - #define __int8_t_defined - #include - #endif - #elif __MINGW32__ /* MINGW */ - #include - #include - #else /* other compilers ...*/ - #include - #include - #include - #endif - - #if !defined(_PTHREAD_H) && !defined(PTHREAD_WIN32) - /** - * to make jack API independent of different thread implementations, - * we define jack_native_thread_t to HANDLE here. - */ - typedef HANDLE jack_native_thread_t; - #else - #ifdef PTHREAD_WIN32 // Added by JE - 10-10-2011 - #include // Makes sure we #include the ptw32 version ! - #endif - /** - * to make jack API independent of different thread implementations, - * we define jack_native_thread_t to pthread_t here. - */ - typedef pthread_t jack_native_thread_t; - #endif - -#endif /* _WIN32 && !__CYGWIN__ && !GNU_WIN32 */ - -#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) - - #if defined(__CYGWIN__) || defined(GNU_WIN32) - #include - #endif - #include - #include - #include - - /** - * to make jack API independent of different thread implementations, - * we define jack_native_thread_t to pthread_t here. - */ - typedef pthread_t jack_native_thread_t; - -#endif /* __APPLE__ || __linux__ || __sun__ || sun */ - -#if defined(__arm__) || defined(__ppc__) || defined(__powerpc__) - #undef POST_PACKED_STRUCTURE - #define POST_PACKED_STRUCTURE -#endif /* __arm__ || __ppc__ || __powerpc__ */ - -#endif /* __jack_systemdeps_h__ */ diff --git a/extern/include/jack/thread.h b/extern/include/jack/thread.h deleted file mode 100644 index 776c5206..00000000 --- a/extern/include/jack/thread.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (C) 2004 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __jack_thread_h__ -#define __jack_thread_h__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include -#include - -/* use 512KB stack per thread - the default is way too high to be feasible - * with mlockall() on many systems */ -#define THREAD_STACK 524288 - -/** @file thread.h - * - * Library functions to standardize thread creation for JACK and its - * clients. These interfaces hide some system variations in the - * handling of realtime scheduling and associated privileges. - */ - -/** - * @defgroup ClientThreads Creating and managing client threads - * @{ - */ - - /** - * @returns if JACK is running with realtime scheduling, this returns - * the priority that any JACK-created client threads will run at. - * Otherwise returns -1. - */ - -int jack_client_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * @returns if JACK is running with realtime scheduling, this returns - * the maximum priority that a JACK client thread should use if the thread - * is subject to realtime scheduling. Otherwise returns -1. - */ - -int jack_client_max_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Attempt to enable realtime scheduling for a thread. On some - * systems that may require special privileges. - * - * @param thread POSIX thread ID. - * @param priority requested thread priority. - * - * @returns 0, if successful; EPERM, if the calling process lacks - * required realtime privileges; otherwise some other error number. - */ -int jack_acquire_real_time_scheduling (jack_native_thread_t thread, int priority) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Create a thread for JACK or one of its clients. The thread is - * created executing @a start_routine with @a arg as its sole - * argument. - * - * @param client the JACK client for whom the thread is being created. May be - * NULL if the client is being created within the JACK server. - * @param thread place to return POSIX thread ID. - * @param priority thread priority, if realtime. - * @param realtime true for the thread to use realtime scheduling. On - * some systems that may require special privileges. - * @param start_routine function the thread calls when it starts. - * @param arg parameter passed to the @a start_routine. - * - * @returns 0, if successful; otherwise some error number. - */ -int jack_client_create_thread (jack_client_t* client, - jack_native_thread_t *thread, - int priority, - int realtime, /* boolean */ - void *(*start_routine)(void*), - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Drop realtime scheduling for a thread. - * - * @param thread POSIX thread ID. - * - * @returns 0, if successful; otherwise an error number. - */ -int jack_drop_real_time_scheduling (jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Stop the thread, waiting for the thread handler to terminate. - * - * @param thread POSIX thread ID. - * - * @returns 0, if successful; otherwise an error number. - */ -int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Kill the thread. - * - * @param thread POSIX thread ID. - * - * @returns 0, if successful; otherwise an error number. - */ - int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; - -#ifndef _WIN32 - - typedef int (*jack_thread_creator_t)(pthread_t*, - const pthread_attr_t*, - void* (*function)(void*), - void* arg); -/** - * This function can be used in very very specialized cases - * where it is necessary that client threads created by JACK - * are created by something other than pthread_create(). After - * it is used, any threads that JACK needs for the client will - * will be created by calling the function passed to this - * function. - * - * No normal application/client should consider calling this. - * The specific case for which it was created involves running - * win32/x86 plugins under Wine on Linux, where it is necessary - * that all threads that might call win32 functions are known - * to Wine. - * - * Set it to NULL to restore thread creation function. - * - * @param creator a function that creates a new thread - * - */ -void jack_set_thread_creator (jack_thread_creator_t creator) JACK_OPTIONAL_WEAK_EXPORT; - -#endif - -/* @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* __jack_thread_h__ */ diff --git a/extern/include/jack/transport.h b/extern/include/jack/transport.h deleted file mode 100644 index 4cec6e03..00000000 --- a/extern/include/jack/transport.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - Copyright (C) 2002 Paul Davis - Copyright (C) 2003 Jack O'Quin - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __jack_transport_h__ -#define __jack_transport_h__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * @defgroup TransportControl Transport and Timebase control - * @{ - */ - -/** - * Called by the timebase master to release itself from that - * responsibility. - * - * If the timebase master releases the timebase or leaves the JACK - * graph for any reason, the JACK engine takes over at the start of - * the next process cycle. The transport state does not change. If - * rolling, it continues to play, with frame numbers as the only - * available position information. - * - * @see jack_set_timebase_callback - * - * @param client the JACK client structure. - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_release_timebase (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Register (or unregister) as a slow-sync client, one that cannot - * respond immediately to transport position changes. - * - * The @a sync_callback will be invoked at the first available - * opportunity after its registration is complete. If the client is - * currently active this will be the following process cycle, - * otherwise it will be the first cycle after calling jack_activate(). - * After that, it runs according to the ::JackSyncCallback rules. - * Clients that don't set a @a sync_callback are assumed to be ready - * immediately any time the transport wants to start. - * - * @param client the JACK client structure. - * @param sync_callback is a realtime function that returns TRUE when - * the client is ready. Setting @a sync_callback to NULL declares that - * this client no longer requires slow-sync processing. - * @param arg an argument for the @a sync_callback function. - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_set_sync_callback (jack_client_t *client, - JackSyncCallback sync_callback, - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Set the timeout value for slow-sync clients. - * - * This timeout prevents unresponsive slow-sync clients from - * completely halting the transport mechanism. The default is two - * seconds. When the timeout expires, the transport starts rolling, - * even if some slow-sync clients are still unready. The @a - * sync_callbacks of these clients continue being invoked, giving them - * a chance to catch up. - * - * @see jack_set_sync_callback - * - * @param client the JACK client structure. - * @param timeout is delay (in microseconds) before the timeout expires. - * - * @return 0 on success, otherwise a non-zero error code. - */ -int jack_set_sync_timeout (jack_client_t *client, - jack_time_t timeout) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Register as timebase master for the JACK subsystem. - * - * The timebase master registers a callback that updates extended - * position information such as beats or timecode whenever necessary. - * Without this extended information, there is no need for this - * function. - * - * There is never more than one master at a time. When a new client - * takes over, the former @a timebase_callback is no longer called. - * Taking over the timebase may be done conditionally, so it fails if - * there was a master already. - * - * @param client the JACK client structure. - * @param conditional non-zero for a conditional request. - * @param timebase_callback is a realtime function that returns - * position information. - * @param arg an argument for the @a timebase_callback function. - * - * @return - * - 0 on success; - * - EBUSY if a conditional request fails because there was already a - * timebase master; - * - other non-zero error code. - */ -int jack_set_timebase_callback (jack_client_t *client, - int conditional, - JackTimebaseCallback timebase_callback, - void *arg) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Reposition the transport to a new frame number. - * - * May be called at any time by any client. The new position takes - * effect in two process cycles. If there are slow-sync clients and - * the transport is already rolling, it will enter the - * ::JackTransportStarting state and begin invoking their @a - * sync_callbacks until ready. This function is realtime-safe. - * - * @see jack_transport_reposition, jack_set_sync_callback - * - * @param client the JACK client structure. - * @param frame frame number of new transport position. - * - * @return 0 if valid request, non-zero otherwise. - */ -int jack_transport_locate (jack_client_t *client, - jack_nframes_t frame) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Query the current transport state and position. - * - * This function is realtime-safe, and can be called from any thread. - * If called from the process thread, @a pos corresponds to the first - * frame of the current cycle and the state returned is valid for the - * entire cycle. - * - * @param client the JACK client structure. - * @param pos pointer to structure for returning current transport - * position; @a pos->valid will show which fields contain valid data. - * If @a pos is NULL, do not return position information. - * - * @return Current transport state. - */ -jack_transport_state_t jack_transport_query (const jack_client_t *client, - jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Return an estimate of the current transport frame, - * including any time elapsed since the last transport - * positional update. - * - * @param client the JACK client structure - */ -jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Request a new transport position. - * - * May be called at any time by any client. The new position takes - * effect in two process cycles. If there are slow-sync clients and - * the transport is already rolling, it will enter the - * ::JackTransportStarting state and begin invoking their @a - * sync_callbacks until ready. This function is realtime-safe. - * - * @see jack_transport_locate, jack_set_sync_callback - * - * @param client the JACK client structure. - * @param pos requested new transport position. - * - * @return 0 if valid request, EINVAL if position structure rejected. - */ -int jack_transport_reposition (jack_client_t *client, - const jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Start the JACK transport rolling. - * - * Any client can make this request at any time. It takes effect no - * sooner than the next process cycle, perhaps later if there are - * slow-sync clients. This function is realtime-safe. - * - * @see jack_set_sync_callback - * - * @param client the JACK client structure. - */ -void jack_transport_start (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Stop the JACK transport. - * - * Any client can make this request at any time. It takes effect on - * the next process cycle. This function is realtime-safe. - * - * @param client the JACK client structure. - */ -void jack_transport_stop (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Gets the current transport info structure (deprecated). - * - * @param client the JACK client structure. - * @param tinfo current transport info structure. The "valid" field - * describes which fields contain valid data. - * - * @deprecated This is for compatibility with the earlier transport - * interface. Use jack_transport_query(), instead. - * - * @pre Must be called from the process thread. - */ -void jack_get_transport_info (jack_client_t *client, - jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_EXPORT; - -/** - * Set the transport info structure (deprecated). - * - * @deprecated This function still exists for compatibility with the - * earlier transport interface, but it does nothing. Instead, define - * a ::JackTimebaseCallback. - */ -void jack_set_transport_info (jack_client_t *client, - jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_EXPORT; - -/*@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* __jack_transport_h__ */ diff --git a/extern/include/jack/types.h b/extern/include/jack/types.h deleted file mode 100644 index 2dccf34f..00000000 --- a/extern/include/jack/types.h +++ /dev/null @@ -1,740 +0,0 @@ -/* - Copyright (C) 2001 Paul Davis - Copyright (C) 2004 Jack O'Quin - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __jack_types_h__ -#define __jack_types_h__ - -#include - -typedef uint64_t jack_uuid_t; - -typedef int32_t jack_shmsize_t; - -/** - * Type used to represent sample frame counts. - */ -typedef uint32_t jack_nframes_t; - -/** - * Maximum value that can be stored in jack_nframes_t - */ -#define JACK_MAX_FRAMES (4294967295U) /* This should be UINT32_MAX, but C++ has a problem with that. */ - -/** - * Type used to represent the value of free running - * monotonic clock with units of microseconds. - */ -typedef uint64_t jack_time_t; - -/** - * Maximum size of @a load_init string passed to an internal client - * jack_initialize() function via jack_internal_client_load(). - */ -#define JACK_LOAD_INIT_LIMIT 1024 - -/** - * jack_intclient_t is an opaque type representing a loaded internal - * client. You may only access it using the API provided in @ref - * intclient.h "". - */ -typedef uint64_t jack_intclient_t; - -/** - * jack_port_t is an opaque type. You may only access it using the - * API provided. - */ -typedef struct _jack_port jack_port_t; - -/** - * jack_client_t is an opaque type. You may only access it using the - * API provided. - */ -typedef struct _jack_client jack_client_t; - -/** - * Ports have unique ids. A port registration callback is the only - * place you ever need to know their value. - */ -typedef uint32_t jack_port_id_t; - -typedef uint32_t jack_port_type_id_t; - -/** - * @ref jack_options_t bits - */ -enum JackOptions { - - /** - * Null value to use when no option bits are needed. - */ - JackNullOption = 0x00, - - /** - * Do not automatically start the JACK server when it is not - * already running. This option is always selected if - * \$JACK_NO_START_SERVER is defined in the calling process - * environment. - */ - JackNoStartServer = 0x01, - - /** - * Use the exact client name requested. Otherwise, JACK - * automatically generates a unique one, if needed. - */ - JackUseExactName = 0x02, - - /** - * Open with optional (char *) server_name parameter. - */ - JackServerName = 0x04, - - /** - * Load internal client from optional (char *) - * load_name. Otherwise use the @a client_name. - */ - JackLoadName = 0x08, - - /** - * Pass optional (char *) load_init string to the - * jack_initialize() entry point of an internal client. - */ - JackLoadInit = 0x10, - - /** - * pass a SessionID Token this allows the sessionmanager to identify the client again. - */ - JackSessionID = 0x20 -}; - -/** Valid options for opening an external client. */ -#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) - -/** Valid options for loading an internal client. */ -#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) - -/** - * Options for several JACK operations, formed by OR-ing together the - * relevant @ref JackOptions bits. - */ -typedef enum JackOptions jack_options_t; - -/** - * @ref jack_status_t bits - */ -enum JackStatus { - - /** - * Overall operation failed. - */ - JackFailure = 0x01, - - /** - * The operation contained an invalid or unsupported option. - */ - JackInvalidOption = 0x02, - - /** - * The desired client name was not unique. With the @ref - * JackUseExactName option this situation is fatal. Otherwise, - * the name was modified by appending a dash and a two-digit - * number in the range "-01" to "-99". The - * jack_get_client_name() function will return the exact string - * that was used. If the specified @a client_name plus these - * extra characters would be too long, the open fails instead. - */ - JackNameNotUnique = 0x04, - - /** - * The JACK server was started as a result of this operation. - * Otherwise, it was running already. In either case the caller - * is now connected to jackd, so there is no race condition. - * When the server shuts down, the client will find out. - */ - JackServerStarted = 0x08, - - /** - * Unable to connect to the JACK server. - */ - JackServerFailed = 0x10, - - /** - * Communication error with the JACK server. - */ - JackServerError = 0x20, - - /** - * Requested client does not exist. - */ - JackNoSuchClient = 0x40, - - /** - * Unable to load internal client - */ - JackLoadFailure = 0x80, - - /** - * Unable to initialize client - */ - JackInitFailure = 0x100, - - /** - * Unable to access shared memory - */ - JackShmFailure = 0x200, - - /** - * Client's protocol version does not match - */ - JackVersionError = 0x400, - - /** - * Backend error - */ - JackBackendError = 0x800, - - /** - * Client zombified failure - */ - JackClientZombie = 0x1000 -}; - -/** - * Status word returned from several JACK operations, formed by - * OR-ing together the relevant @ref JackStatus bits. - */ -typedef enum JackStatus jack_status_t; - -/** - * @ref jack_latency_callback_mode_t - */ -enum JackLatencyCallbackMode { - - /** - * Latency Callback for Capture Latency. - * Input Ports have their latency value setup. - * In the Callback the client needs to set the latency of the output ports - */ - JackCaptureLatency, - - /** - * Latency Callback for Playback Latency. - * Output Ports have their latency value setup. - * In the Callback the client needs to set the latency of the input ports - */ - JackPlaybackLatency - -}; - -/** - * Type of Latency Callback (Capture or Playback) - */ -typedef enum JackLatencyCallbackMode jack_latency_callback_mode_t; - -/** - * Prototype for the client supplied function that is called - * by the engine when port latencies need to be recalculated - * - * @param mode playback or capture latency - * @param arg pointer to a client supplied data - * - * @return zero on success, non-zero on error - */ -typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void *arg); - -/** - * the new latency API operates on Ranges. - */ -PRE_PACKED_STRUCTURE -struct _jack_latency_range -{ - /** - * minimum latency - */ - jack_nframes_t min; - /** - * maximum latency - */ - jack_nframes_t max; -} POST_PACKED_STRUCTURE; - -typedef struct _jack_latency_range jack_latency_range_t; - -/** - * Prototype for the client supplied function that is called - * by the engine anytime there is work to be done. - * - * @pre nframes == jack_get_buffer_size() - * @pre nframes == pow(2,x) - * - * @param nframes number of frames to process - * @param arg pointer to a client supplied structure - * - * @return zero on success, non-zero on error - */ -typedef int (*JackProcessCallback)(jack_nframes_t nframes, void *arg); - -/** - * Prototype for the client thread routine called - * by the engine when the client is inserted in the graph. - * - * @param arg pointer to a client supplied structure - * - */ -typedef void *(*JackThreadCallback)(void* arg); - -/** - * Prototype for the client supplied function that is called - * once after the creation of the thread in which other - * callbacks will be made. Special thread characteristics - * can be set from this callback, for example. This is a - * highly specialized callback and most clients will not - * and should not use it. - * - * @param arg pointer to a client supplied structure - * - * @return void - */ -typedef void (*JackThreadInitCallback)(void *arg); - -/** - * Prototype for the client supplied function that is called - * whenever the processing graph is reordered. - * - * @param arg pointer to a client supplied structure - * - * @return zero on success, non-zero on error - */ -typedef int (*JackGraphOrderCallback)(void *arg); - -/** - * Prototype for the client-supplied function that is called whenever - * an xrun has occured. - * - * @see jack_get_xrun_delayed_usecs() - * - * @param arg pointer to a client supplied structure - * - * @return zero on success, non-zero on error - */ -typedef int (*JackXRunCallback)(void *arg); - -/** - * Prototype for the @a bufsize_callback that is invoked whenever the - * JACK engine buffer size changes. Although this function is called - * in the JACK process thread, the normal process cycle is suspended - * during its operation, causing a gap in the audio flow. So, the @a - * bufsize_callback can allocate storage, touch memory not previously - * referenced, and perform other operations that are not realtime - * safe. - * - * @param nframes buffer size - * @param arg pointer supplied by jack_set_buffer_size_callback(). - * - * @return zero on success, non-zero on error - */ -typedef int (*JackBufferSizeCallback)(jack_nframes_t nframes, void *arg); - -/** - * Prototype for the client supplied function that is called - * when the engine sample rate changes. - * - * @param nframes new engine sample rate - * @param arg pointer to a client supplied structure - * - * @return zero on success, non-zero on error - */ -typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void *arg); - -/** - * Prototype for the client supplied function that is called - * whenever a port is registered or unregistered. - * - * @param port the ID of the port - * @param arg pointer to a client supplied data - * @param register non-zero if the port is being registered, - * zero if the port is being unregistered - */ -typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int /* register */, void *arg); - -/** - * Prototype for the client supplied function that is called - * whenever a client is registered or unregistered. - * - * @param name a null-terminated string containing the client name - * @param register non-zero if the client is being registered, - * zero if the client is being unregistered - * @param arg pointer to a client supplied structure - */ -typedef void (*JackClientRegistrationCallback)(const char* name, int /* register */, void *arg); - -/** - * Prototype for the client supplied function that is called - * whenever a port is connected or disconnected. - * - * @param a one of two ports connected or disconnected - * @param b one of two ports connected or disconnected - * @param connect non-zero if ports were connected - * zero if ports were disconnected - * @param arg pointer to a client supplied data - */ -typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); - -/** - * Prototype for the client supplied function that is called - * whenever the port name has been changed. - * - * @param port the port that has been renamed - * @param new_name the new name - * @param arg pointer to a client supplied structure - */ -typedef void (*JackPortRenameCallback)(jack_port_id_t port, const char* old_name, const char* new_name, void *arg); - -/** - * Prototype for the client supplied function that is called - * whenever jackd starts or stops freewheeling. - * - * @param starting non-zero if we start starting to freewheel, zero otherwise - * @param arg pointer to a client supplied structure - */ -typedef void (*JackFreewheelCallback)(int starting, void *arg); - -/** - * Prototype for the client supplied function that is called - * whenever jackd is shutdown. Note that after server shutdown, - * the client pointer is *not* deallocated by libjack, - * the application is responsible to properly use jack_client_close() - * to release client ressources. Warning: jack_client_close() cannot be - * safely used inside the shutdown callback and has to be called outside of - * the callback context. - * - * @param arg pointer to a client supplied structure - */ -typedef void (*JackShutdownCallback)(void *arg); - -/** - * Prototype for the client supplied function that is called - * whenever jackd is shutdown. Note that after server shutdown, - * the client pointer is *not* deallocated by libjack, - * the application is responsible to properly use jack_client_close() - * to release client ressources. Warning: jack_client_close() cannot be - * safely used inside the shutdown callback and has to be called outside of - * the callback context. - - * @param code a status word, formed by OR-ing together the relevant @ref JackStatus bits. - * @param reason a string describing the shutdown reason (backend failure, server crash... etc...). - * Note that this string will not be available anymore after the callback returns, so possibly copy it. - * @param arg pointer to a client supplied structure - */ -typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg); - -/** - * Used for the type argument of jack_port_register() for default - * audio ports and midi ports. - */ -#define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" -#define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi" - -/** - * For convenience, use this typedef if you want to be able to change - * between float and double. You may want to typedef sample_t to - * jack_default_audio_sample_t in your application. - */ -typedef float jack_default_audio_sample_t; - -/** - * A port has a set of flags that are formed by AND-ing together the - * desired values from the list below. The flags "JackPortIsInput" and - * "JackPortIsOutput" are mutually exclusive and it is an error to use - * them both. - */ -enum JackPortFlags { - - /** - * if JackPortIsInput is set, then the port can receive - * data. - */ - JackPortIsInput = 0x1, - - /** - * if JackPortIsOutput is set, then data can be read from - * the port. - */ - JackPortIsOutput = 0x2, - - /** - * if JackPortIsPhysical is set, then the port corresponds - * to some kind of physical I/O connector. - */ - JackPortIsPhysical = 0x4, - - /** - * if JackPortCanMonitor is set, then a call to - * jack_port_request_monitor() makes sense. - * - * Precisely what this means is dependent on the client. A typical - * result of it being called with TRUE as the second argument is - * that data that would be available from an output port (with - * JackPortIsPhysical set) is sent to a physical output connector - * as well, so that it can be heard/seen/whatever. - * - * Clients that do not control physical interfaces - * should never create ports with this bit set. - */ - JackPortCanMonitor = 0x8, - - /** - * JackPortIsTerminal means: - * - * for an input port: the data received by the port - * will not be passed on or made - * available at any other port - * - * for an output port: the data available at the port - * does not originate from any other port - * - * Audio synthesizers, I/O hardware interface clients, HDR - * systems are examples of clients that would set this flag for - * their ports. - */ - JackPortIsTerminal = 0x10, - -}; - -/** - * Transport states. - */ -typedef enum { - - /* the order matters for binary compatibility */ - JackTransportStopped = 0, /**< Transport halted */ - JackTransportRolling = 1, /**< Transport playing */ - JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */ - JackTransportStarting = 3, /**< Waiting for sync ready */ - JackTransportNetStarting = 4, /**< Waiting for sync ready on the network*/ - -} jack_transport_state_t; - -typedef uint64_t jack_unique_t; /**< Unique ID (opaque) */ - -/** - * Optional struct jack_position_t fields. - */ -typedef enum { - - JackPositionBBT = 0x10, /**< Bar, Beat, Tick */ - JackPositionTimecode = 0x20, /**< External timecode */ - JackBBTFrameOffset = 0x40, /**< Frame offset of BBT information */ - JackAudioVideoRatio = 0x80, /**< audio frames per video frame */ - JackVideoFrameOffset = 0x100 /**< frame offset of first video frame */ - -} jack_position_bits_t; - -/** all valid position bits */ -#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode) -#define EXTENDED_TIME_INFO - -PRE_PACKED_STRUCTURE -struct _jack_position { - - /* these four cannot be set from clients: the server sets them */ - jack_unique_t unique_1; /**< unique ID */ - jack_time_t usecs; /**< monotonic, free-rolling */ - jack_nframes_t frame_rate; /**< current frame rate (per second) */ - jack_nframes_t frame; /**< frame number, always present */ - - jack_position_bits_t valid; /**< which other fields are valid */ - - /* JackPositionBBT fields: */ - int32_t bar; /**< current bar */ - int32_t beat; /**< current beat-within-bar */ - int32_t tick; /**< current tick-within-beat */ - double bar_start_tick; - - float beats_per_bar; /**< time signature "numerator" */ - float beat_type; /**< time signature "denominator" */ - double ticks_per_beat; - double beats_per_minute; - - /* JackPositionTimecode fields: (EXPERIMENTAL: could change) */ - double frame_time; /**< current time in seconds */ - double next_time; /**< next sequential frame_time - (unless repositioned) */ - - /* JackBBTFrameOffset fields: */ - jack_nframes_t bbt_offset; /**< frame offset for the BBT fields - (the given bar, beat, and tick - values actually refer to a time - frame_offset frames before the - start of the cycle), should - be assumed to be 0 if - JackBBTFrameOffset is not - set. If JackBBTFrameOffset is - set and this value is zero, the BBT - time refers to the first frame of this - cycle. If the value is positive, - the BBT time refers to a frame that - many frames before the start of the - cycle. */ - - /* JACK video positional data (experimental) */ - - float audio_frames_per_video_frame; /**< number of audio frames - per video frame. Should be assumed - zero if JackAudioVideoRatio is not - set. If JackAudioVideoRatio is set - and the value is zero, no video - data exists within the JACK graph */ - - jack_nframes_t video_offset; /**< audio frame at which the first video - frame in this cycle occurs. Should - be assumed to be 0 if JackVideoFrameOffset - is not set. If JackVideoFrameOffset is - set, but the value is zero, there is - no video frame within this cycle. */ - - /* For binary compatibility, new fields should be allocated from - * this padding area with new valid bits controlling access, so - * the existing structure size and offsets are preserved. */ - int32_t padding[7]; - - /* When (unique_1 == unique_2) the contents are consistent. */ - jack_unique_t unique_2; /**< unique ID */ - -} POST_PACKED_STRUCTURE; - -typedef struct _jack_position jack_position_t; - -/** - * Prototype for the @a sync_callback defined by slow-sync clients. - * When the client is active, this callback is invoked just before - * process() in the same thread. This occurs once after registration, - * then subsequently whenever some client requests a new position, or - * the transport enters the ::JackTransportStarting state. This - * realtime function must not wait. - * - * The transport @a state will be: - * - * - ::JackTransportStopped when a new position is requested; - * - ::JackTransportStarting when the transport is waiting to start; - * - ::JackTransportRolling when the timeout has expired, and the - * position is now a moving target. - * - * @param state current transport state. - * @param pos new transport position. - * @param arg the argument supplied by jack_set_sync_callback(). - * - * @return TRUE (non-zero) when ready to roll. - */ -typedef int (*JackSyncCallback)(jack_transport_state_t state, - jack_position_t *pos, - void *arg); - - -/** - * Prototype for the @a timebase_callback used to provide extended - * position information. Its output affects all of the following - * process cycle. This realtime function must not wait. - * - * This function is called immediately after process() in the same - * thread whenever the transport is rolling, or when any client has - * requested a new position in the previous cycle. The first cycle - * after jack_set_timebase_callback() is also treated as a new - * position, or the first cycle after jack_activate() if the client - * had been inactive. - * - * The timebase master may not use its @a pos argument to set @a - * pos->frame. To change position, use jack_transport_reposition() or - * jack_transport_locate(). These functions are realtime-safe, the @a - * timebase_callback can call them directly. - * - * @param state current transport state. - * @param nframes number of frames in current period. - * @param pos address of the position structure for the next cycle; @a - * pos->frame will be its frame number. If @a new_pos is FALSE, this - * structure contains extended position information from the current - * cycle. If TRUE, it contains whatever was set by the requester. - * The @a timebase_callback's task is to update the extended - * information here. - * @param new_pos TRUE (non-zero) for a newly requested @a pos, or for - * the first cycle after the @a timebase_callback is defined. - * @param arg the argument supplied by jack_set_timebase_callback(). - */ -typedef void (*JackTimebaseCallback)(jack_transport_state_t state, - jack_nframes_t nframes, - jack_position_t *pos, - int new_pos, - void *arg); - -/********************************************************************* - * The following interfaces are DEPRECATED. They are only provided - * for compatibility with the earlier JACK transport implementation. - *********************************************************************/ - -/** - * Optional struct jack_transport_info_t fields. - * - * @see jack_position_bits_t. - */ -typedef enum { - - JackTransportState = 0x1, /**< Transport state */ - JackTransportPosition = 0x2, /**< Frame number */ - JackTransportLoop = 0x4, /**< Loop boundaries (ignored) */ - JackTransportSMPTE = 0x8, /**< SMPTE (ignored) */ - JackTransportBBT = 0x10 /**< Bar, Beat, Tick */ - -} jack_transport_bits_t; - -/** - * Deprecated struct for transport position information. - * - * @deprecated This is for compatibility with the earlier transport - * interface. Use the jack_position_t struct, instead. - */ -typedef struct { - - /* these two cannot be set from clients: the server sets them */ - - jack_nframes_t frame_rate; /**< current frame rate (per second) */ - jack_time_t usecs; /**< monotonic, free-rolling */ - - jack_transport_bits_t valid; /**< which fields are legal to read */ - jack_transport_state_t transport_state; - jack_nframes_t frame; - jack_nframes_t loop_start; - jack_nframes_t loop_end; - - long smpte_offset; /**< SMPTE offset (from frame 0) */ - float smpte_frame_rate; /**< 29.97, 30, 24 etc. */ - - int bar; - int beat; - int tick; - double bar_start_tick; - - float beats_per_bar; - float beat_type; - double ticks_per_beat; - double beats_per_minute; - -} jack_transport_info_t; - - -#endif /* __jack_types_h__ */ diff --git a/extern/include/jack/weakjack.h b/extern/include/jack/weakjack.h deleted file mode 100644 index 652d58ab..00000000 --- a/extern/include/jack/weakjack.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright (C) 2010 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __weakjack_h__ -#define __weakjack_h__ - -/** - * @defgroup WeakLinkage Managing support for newer/older versions of JACK - * @{ One challenge faced by developers is that of taking - * advantage of new features introduced in new versions - * of [ JACK ] while still supporting older versions of - * the system. Normally, if an application uses a new - * feature in a library/API, it is unable to run on - * earlier versions of the library/API that do not - * support that feature. Such applications would either - * fail to launch or crash when an attempt to use the - * feature was made. This problem cane be solved using - * weakly-linked symbols. - * - * When a symbol in a framework is defined as weakly - * linked, the symbol does not have to be present at - * runtime for a process to continue running. The static - * linker identifies a weakly linked symbol as such in - * any code module that references the symbol. The - * dynamic linker uses this same information at runtime - * to determine whether a process can continue - * running. If a weakly linked symbol is not present in - * the framework, the code module can continue to run as - * long as it does not reference the symbol. However, if - * the symbol is present, the code can use it normally. - * - * (adapted from: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html) - * - * A concrete example will help. Suppose that someone uses a version - * of a JACK client we'll call "Jill". Jill was linked against a version - * of JACK that contains a newer part of the API (say, jack_set_latency_callback()) - * and would like to use it if it is available. - * - * When Jill is run on a system that has a suitably "new" version of - * JACK, this function will be available entirely normally. But if Jill - * is run on a system with an old version of JACK, the function isn't - * available. - * - * With normal symbol linkage, this would create a startup error whenever - * someone tries to run Jill with the "old" version of JACK. However, functions - * added to JACK after version 0.116.2 are all declared to have "weak" linkage - * which means that their abscence doesn't cause an error during program - * startup. Instead, Jill can test whether or not the symbol jack_set_latency_callback - * is null or not. If its null, it means that the JACK installed on this machine - * is too old to support this function. If its not null, then Jill can use it - * just like any other function in the API. For example: - * - * \code - * if (jack_set_latency_callback) { - * jack_set_latency_callback (jill_client, jill_latency_callback, arg); - * } - * \endcode - * - * However, there are clients that may want to use this approach to parts of the - * the JACK API that predate 0.116.2. For example, they might want to see if even - * really old basic parts of the API like jack_client_open() exist at runtime. - * - * Such clients should include before any other JACK header. - * This will make the \b entire JACK API be subject to weak linkage, so that any - * and all functions can be checked for existence at runtime. It is important - * to understand that very few clients need to do this - if you use this - * feature you should have a clear reason to do so. - * - * - */ - -#ifdef __APPLE__ -#define WEAK_ATTRIBUTE weak_import -#else -#define WEAK_ATTRIBUTE __weak__ -#endif - -#ifndef JACK_OPTIONAL_WEAK_EXPORT -/* JACK_OPTIONAL_WEAK_EXPORT needs to be a macro which - expands into a compiler directive. If non-null, the directive - must tell the compiler to arrange for weak linkage of - the symbol it used with. For this to work fully may - require linker arguments for the client as well. -*/ -#ifdef __GNUC__ -#define JACK_OPTIONAL_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) -#else -/* Add other things here for non-gcc platforms */ -#endif -#endif - -#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT -/* JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT needs to be a macro - which expands into a compiler directive. If non-null, the directive - must tell the compiler to arrange for weak linkage of the - symbol it is used with AND optionally to mark the symbol - as deprecated. For this to work fully may require - linker arguments for the client as well. -*/ -#ifdef __GNUC__ -#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((WEAK_ATTRIBUTE,__deprecated__)) -#else -/* Add other things here for non-gcc platforms */ -#endif -#endif - -/*@}*/ - -#endif /* weakjack */ diff --git a/extern/include/jack/weakmacros.h b/extern/include/jack/weakmacros.h deleted file mode 100644 index 944fddb9..00000000 --- a/extern/include/jack/weakmacros.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 2010 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __weakmacros_h__ -#define __weakmacros_h__ - -/************************************************************* - * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function - * added to the JACK API after the 0.116.2 release. - * - * Functions that predate this release are marked with - * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile - * time in a variety of ways. The default definition is empty, - * so that these symbols get normal linkage. If you wish to - * use all JACK symbols with weak linkage, include - * before jack.h. - *************************************************************/ - -#ifdef __APPLE__ -#define WEAK_ATTRIBUTE weak_import -#else -#define WEAK_ATTRIBUTE __weak__ -#endif - -#ifndef JACK_WEAK_EXPORT -#ifdef __GNUC__ -/* JACK_WEAK_EXPORT needs to be a macro which - expands into a compiler directive. If non-null, the directive - must tell the compiler to arrange for weak linkage of - the symbol it used with. For this to work full may - require linker arguments in the client as well. -*/ - -#ifdef _WIN32 - /* - Not working with __declspec(dllexport) so normal linking - Linking with JackWeakAPI.cpp will be the preferred way. - */ - #define JACK_WEAK_EXPORT -#else - #define JACK_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) -#endif - -#else -/* Add other things here for non-gcc platforms */ - -#ifdef _WIN32 -#define JACK_WEAK_EXPORT -#endif - -#endif -#endif - -#ifndef JACK_WEAK_EXPORT -#define JACK_WEAK_EXPORT -#endif - -#ifndef JACK_OPTIONAL_WEAK_EXPORT -#define JACK_OPTIONAL_WEAK_EXPORT -#endif - -#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT -#ifdef __GNUC__ -#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((__deprecated__)) -#else -/* Add other things here for non-gcc platforms */ - -#ifdef _WIN32 -#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT -#endif - -#endif /* __GNUC__ */ - -#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT -#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT -#endif - -#endif - -#endif /* __weakmacros_h__ */ - From 83d5e51d09ad2183590e36872bb9ccf6e838abdb Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 14:19:50 +0200 Subject: [PATCH 05/44] make jack audio headers a submodule --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index 17d1ac6a..59306e80 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "extern/include/asio"] path = extern/include/asio url = https://github.com/chriskohlhoff/asio.git +[submodule "extern/include/jack"] + path = extern/include/jack + url = https://github.com/jackaudio/headers.git From 6a6039a751b0e226e087e86104356785a45a9a09 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 14:20:05 +0200 Subject: [PATCH 06/44] Update .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 324d18fc..4e83e25c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ data/Makefile.in man/Makefile.in src/Makefile.in src/config.h.in +src/config.h +_build/ +bin/ + From 9f0af261b17761834466a8921997f56203243514 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 14:24:30 +0200 Subject: [PATCH 07/44] Create jack --- extern/include/jack | 1 + 1 file changed, 1 insertion(+) create mode 160000 extern/include/jack diff --git a/extern/include/jack b/extern/include/jack new file mode 160000 index 00000000..2bfa5069 --- /dev/null +++ b/extern/include/jack @@ -0,0 +1 @@ +Subproject commit 2bfa5069718ca4f4dc091e0be845958f2d8a5ba8 From c008e7a93cfb165c4dcb2d3735a6ef91f1279f5f Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 15:10:22 +0200 Subject: [PATCH 08/44] Enable Websocket interface --- .gitmodules | 3 +++ CMakeLists.txt | 41 ++++++++++++++++++++++++-------------- extern/include/websocketpp | 1 + generate_config.h.in | 5 ++++- 4 files changed, 34 insertions(+), 16 deletions(-) create mode 160000 extern/include/websocketpp diff --git a/.gitmodules b/.gitmodules index 59306e80..161d9db4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "extern/include/jack"] path = extern/include/jack url = https://github.com/jackaudio/headers.git +[submodule "extern/include/websocketpp"] + path = extern/include/websocketpp + url = https://github.com/zaphoyd/websocketpp.git diff --git a/CMakeLists.txt b/CMakeLists.txt index d65e2078..7df28bfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.8) project(SSR) # The version number -set(SSR_VERSION 0.5.1-cmake) +set(SSR_VERSION 0.6.0-cmake) # Show more of make set(CMAKE_VERBOSE_MAKEFILE ON) @@ -210,14 +210,27 @@ else(GUI) endif(GUI) # Network -option(ENABLE_IP_INTERFACE "network (TCP/IP) interface (legacy)" ON) -if(ENABLE_IP_INTERFACE) - #list(APPEND SOURCE_FILES - # src/network/commandparser.cpp - # src/network/connection.cpp - # src/network/networksubscriber.cpp - # src/network/server.cpp - # ) +option(ENABLE_WEBSOCKET_INTERFACE "network websocket interface" ON) +if(ENABLE_WEBSOCKET_INTERFACE) + add_definitions(-DASIO_STANDALONE) + set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) + include_directories(${ASIO_PATH}) + + add_definitions(-D_WEBSOCKETPP_CPP11_THREAD_) # https://github.com/zaphoyd/websocketpp/issues/980 + include_directories(${EXTERN_PATH}/include/websocketpp) + set(RAPIDJSON_PATH ${PROJECT_SOURCE_DIR}/rapidjson) + include_directories(${RAPIDJSON_PATH}/include/) + + set(WEBSOCKET_PATH ${PROJECT_SOURCE_DIR}/src/websocket/) + include_directories(${WEBSOCKET_PATH}) + message(STATUS "Enabled WEBSOCKET_INTERFACE interface") +else(ENABLE_WEBSOCKET_INTERFACE) + message(WARNING "WEBSOCKET_INTERFACE disabled.") +endif(ENABLE_WEBSOCKET_INTERFACE) + +option(ENABLE_LEGACY_NETWORK_INTERFACE "network (TCP/IP) interface (legacy)" ON) +if(ENABLE_LEGACY_NETWORK_INTERFACE) + add_definitions(-DASIO_STANDALONE) set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) include_directories(${ASIO_PATH}) @@ -225,16 +238,14 @@ if(ENABLE_IP_INTERFACE) list(APPEND SOURCE_FILES ${NETWORK_SOURCE_FILES}) include_directories(${PROJECT_SOURCE_DIR}/src/legacy_network) - add_definitions(-DASIO_STANDALONE) if(WIN32) add_definitions(-D_WIN32_WINNT=0x0601) # Windows 7 list(APPEND LINKLIBS "-lws2_32 -lmswsock") endif(WIN32) - message(STATUS "Enabled network interface (legacy)") - -else(ENABLE_IP_INTERFACE) - message(WARNING "IP_INTERFACE disabled.") -endif(ENABLE_IP_INTERFACE) + message(STATUS "Enabled LEGACY_NETWORK interface") +else(ENABLE_LEGACY_NETWORK_INTERFACE) + message(WARNING "LEGACY_NETWORK_INTERFACE disabled.") +endif(ENABLE_LEGACY_NETWORK_INTERFACE) # Head tracker option(HEAD_TRACKER "Basic head tracker support" ON) diff --git a/extern/include/websocketpp b/extern/include/websocketpp new file mode 160000 index 00000000..1b11fd30 --- /dev/null +++ b/extern/include/websocketpp @@ -0,0 +1 @@ +Subproject commit 1b11fd301531e6df35a6107c1e8665b1e77a2d8e diff --git a/generate_config.h.in b/generate_config.h.in index f09c164e..13d06b9f 100644 --- a/generate_config.h.in +++ b/generate_config.h.in @@ -10,9 +10,12 @@ /* Ecasound soundfile playback/recording */ #cmakedefine ENABLE_ECASOUND 1 -/* network (TCP/IP) interface */ +/* network (TCP/IP) interface : LEGACY*/ #cmakedefine ENABLE_IP_INTERFACE 1 +/* network (TCP/IP) interface : WEBSOCKET*/ +#cmakedefine ENABLE_WEBSOCKET_INTERFACE 1 + /* Razor AHRS tracker support */ #cmakedefine ENABLE_RAZOR 1 From 64b636a92953026b2f9923b2f3f31033836c09e9 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Wed, 1 Feb 2023 19:47:38 +0200 Subject: [PATCH 09/44] Make cmake clearer --- .gitignore | 1 + CMakeLists.txt | 10 +++++----- generate_config.h.in | 18 +++++++++--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 4e83e25c..0f28c503 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ src/config.h _build/ bin/ +*.exe diff --git a/CMakeLists.txt b/CMakeLists.txt index 7df28bfb..af3b9bb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(CMAKE_VERBOSE_MAKEFILE ON) # Set the output folder where your program will be created set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/_build) if(WIN32) - set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) + set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/ssr-win-bin) else(WIN32) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/src) endif(WIN32) @@ -157,7 +157,7 @@ if(GUI) # src/gui/qvolumeslider.cpp # src/gui/qzoomlabel.cpp # ) - AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src/gui GUI_SOURCE_FILES) + aux_source_directory(${PROJECT_SOURCE_DIR}/src/gui GUI_SOURCE_FILES) list(APPEND SOURCE_FILES ${GUI_SOURCE_FILES}) option(ENABLE_GUI "graphical user interface (using Qt)" ON) @@ -228,18 +228,18 @@ else(ENABLE_WEBSOCKET_INTERFACE) message(WARNING "WEBSOCKET_INTERFACE disabled.") endif(ENABLE_WEBSOCKET_INTERFACE) -option(ENABLE_LEGACY_NETWORK_INTERFACE "network (TCP/IP) interface (legacy)" ON) +option(ENABLE_LEGACY_NETWORK_INTERFACE "network xml interface (legacy)" ON) if(ENABLE_LEGACY_NETWORK_INTERFACE) add_definitions(-DASIO_STANDALONE) set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) include_directories(${ASIO_PATH}) - AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src/legacy_network NETWORK_SOURCE_FILES) + aux_source_directory(${PROJECT_SOURCE_DIR}/src/legacy_network NETWORK_SOURCE_FILES) list(APPEND SOURCE_FILES ${NETWORK_SOURCE_FILES}) include_directories(${PROJECT_SOURCE_DIR}/src/legacy_network) if(WIN32) - add_definitions(-D_WIN32_WINNT=0x0601) # Windows 7 + #add_definitions(-D_WIN32_WINNT=0x0601) # Windows 7 list(APPEND LINKLIBS "-lws2_32 -lmswsock") endif(WIN32) message(STATUS "Enabled LEGACY_NETWORK interface") diff --git a/generate_config.h.in b/generate_config.h.in index 13d06b9f..143e74a1 100644 --- a/generate_config.h.in +++ b/generate_config.h.in @@ -2,25 +2,25 @@ /* graphical user interface (using Qt) */ -#cmakedefine ENABLE_GUI 1 +#cmakedefine ENABLE_GUI @ENABLE_GUI@ /* separate control window */ -#cmakedefine ENABLE_FLOATING_CONTROL_PANEL 1 +#cmakedefine ENABLE_FLOATING_CONTROL_PANEL @ENABLE_FLOATING_CONTROL_PANEL@ /* Ecasound soundfile playback/recording */ -#cmakedefine ENABLE_ECASOUND 1 +#cmakedefine ENABLE_ECASOUND 0 -/* network (TCP/IP) interface : LEGACY*/ -#cmakedefine ENABLE_IP_INTERFACE 1 +/* XML network (TCP/IP) interface : LEGACY*/ +#cmakedefine ENABLE_IP_INTERFACE @ENABLE_LEGACY_NETWORK_INTERFACE@ -/* network (TCP/IP) interface : WEBSOCKET*/ -#cmakedefine ENABLE_WEBSOCKET_INTERFACE 1 +/* Websocket++ network (TCP/IP) interface : WEBSOCKET*/ +#cmakedefine ENABLE_WEBSOCKET_INTERFACE @ENABLE_WEBSOCKET_INTERFACE@ /* Razor AHRS tracker support */ -#cmakedefine ENABLE_RAZOR 1 +#cmakedefine ENABLE_RAZOR @HEAD_TRACKER@ /* Polhemus Fastrak/Patriot tracker support */ -#cmakedefine ENABLE_POLHEMUS 1 +#cmakedefine ENABLE_POLHEMUS @HEAD_TRACKER@ /*?? support for isatty() ??*/ #cmakedefine ENABLE_ISATTY 1 From a71316c10612cf320b1dbf9cda1068a0f90c7a49 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Thu, 16 Feb 2023 14:04:22 +0200 Subject: [PATCH 10/44] Update CMakeLists.txt --- CMakeLists.txt | 105 +++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af3b9bb2..84000b55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,10 @@ set(SSR_VERSION 0.6.0-cmake) # Show more of make set(CMAKE_VERBOSE_MAKEFILE ON) +# shared or static build +option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +message(STATUS "Shared libs: " ${BUILD_SHARED_LIBS}) + # Set the output folder where your program will be created set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/_build) if(WIN32) @@ -55,7 +59,7 @@ set(SOURCE_FILES # Add libraries to LINKLIBS set(LINKLIBS) -set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +#set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) @@ -65,15 +69,16 @@ find_package(PkgConfig REQUIRED) if(WIN32) # Set Path to extern headers and libraries for Windows builds set(EXTERN_PATH ${PROJECT_SOURCE_DIR}/extern) - set(CMAKE_PREFIX_PATH ${EXTERN_PATH}) - message(STATUS "WINDOWS Prefix: " ${CMAKE_PREFIX_PATH}) + + #set(CMAKE_PREFIX_PATH ${EXTERN_PATH}) + #message(STATUS "WINDOWS Prefix: " ${CMAKE_PREFIX_PATH}) # Include extern headers include_directories(${EXTERN_PATH}/include) - message(STATUS "WINDOWS Included: " ${EXTERN_PATH}/include) + message(STATUS "Included: " ${EXTERN_PATH}/include) # here is the target environment located - set (CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${EXTERN_PATH}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${EXTERN_PATH}) endif(WIN32) if(WIN32) @@ -81,12 +86,14 @@ if(WIN32) #if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # find_library(LibXml2 NAMES libxml2_msvc) #endif() + if(NOT ${BUILD_SHARED_LIBS}) + add_definitions(-DLIBXML_STATIC) + endif() find_package(LibXml2 REQUIRED) include_directories(${LIBXML2_INCLUDE_DIR}) list(APPEND LINKLIBS ${LIBXML2_LIBRARY}) - add_definitions(-DLIBXML_STATIC) #list(APPEND LINKLIBS "-lxml2 -lz -llzma -lws2_32") - list(APPEND LINKLIBS "-llzma") + list(APPEND LINKLIBS "-llzma -lz") message(STATUS "Found XML2: " ${LIBXML2_LIBRARY}) message(STATUS "Found XML2 headers: " ${LIBXML2_INCLUDE_DIR}) else(WIN32) @@ -119,12 +126,6 @@ find_library(JACK_LIBRARY NAMES jack libjack64) list(APPEND LINKLIBS ${JACK_LIBRARY}) message(STATUS "Found JACK :" ${JACK_LIBRARY}) -if(WIN32) - find_library(JACKSERVER_LIBRARY NAMES libjackserver64) - list(APPEND LINKLIBS ${JACKSERVER_LIBRARY}) - message(STATUS "Found JACK :" ${JACKSERVER_LIBRARY}) -endif(WIN32) - find_library(FFTW_LIBRARY NAMES fftw3 libfftw3-3) list(APPEND LINKLIBS ${FFTW_LIBRARY}) message(STATUS "Found FFTW: " ${FFTW_LIBRARY}) @@ -134,7 +135,7 @@ list(APPEND LINKLIBS ${FFTWF_LIBRARY}) message(STATUS "Found FFTWF: " ${FFTWF_LIBRARY}) # GUI -option(GUI "Build GUI" ON) +option(GUI "Build GUI" OFF) if(GUI) # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -142,32 +143,20 @@ if(GUI) set(CMAKE_AUTOMOC ON) include_directories(${PROJECT_SOURCE_DIR}/src/gui) # necessary? - #set(GUI_SOURCE_FILES - # src/gui/qclicktextlabel.cpp - # src/gui/qcpulabel.cpp - # src/gui/qfilemenulabel.cpp - # src/gui/qgui.cpp - # src/gui/qguiframe.cpp - # src/gui/qopenglplotter.cpp - # src/gui/qscenebutton.cpp - # src/gui/qsourceproperties.cpp - # src/gui/qssrtimeline.cpp - # src/gui/qtimeedit.cpp - # src/gui/quserinterface.cpp - # src/gui/qvolumeslider.cpp - # src/gui/qzoomlabel.cpp - # ) aux_source_directory(${PROJECT_SOURCE_DIR}/src/gui GUI_SOURCE_FILES) list(APPEND SOURCE_FILES ${GUI_SOURCE_FILES}) option(ENABLE_GUI "graphical user interface (using Qt)" ON) - option(ENABLE_FLOATING_CONTROL_PANEL "separate control window" ON) - option(STATIC_QT "Use static Qt5 libraries (Windows)" ON) + option(ENABLE_FLOATING_CONTROL_PANEL "separate control window" OFF) + find_package(Qt5 COMPONENTS Core Gui Widgets OpenGL REQUIRED) message(STATUS "Found QT5: " ${Qt5_DIR}) if(WIN32) + if(NOT ${BUILD_SHARED_LIBS}) + option(STATIC_QT "Use static Qt5 libraries (Windows)" ON) + endif() if(STATIC_QT) add_definitions(-DQT_STATICPLUGIN) endif(STATIC_QT) @@ -178,6 +167,8 @@ if(GUI) ) # Qt5PlatformSupport modules + find_library(Qt5PlatformCompositorSupportLIBRARY Qt5PlatformCompositorSupport) + list(APPEND QT5PLATFORMSUPPORT_LIBS ${Qt5PlatformCompositorSupportLIBRARY}) find_library(Qt5ThemeSupport_LIBRARY Qt5ThemeSupport) list(APPEND QT5PLATFORMSUPPORT_LIBS ${Qt5ThemeSupport_LIBRARY}) find_library(Qt5FontDatabaseSupport_LIBRARY Qt5FontDatabaseSupport) @@ -192,7 +183,7 @@ if(GUI) find_package(Freetype REQUIRED) list(APPEND QT5PLATFORMSUPPORT_LIBS ${FREETYPE_LIBRARIES}) - list(APPEND QT5PLATFORMSUPPORT_LIBS "-lwtsapi32") + #list(APPEND QT5PLATFORMSUPPORT_LIBS "-lwtsapi32") message(STATUS "Found Qt5PlatformSupport: " ${QT5PLATFORMSUPPORT_LIBS}) endif(WIN32) @@ -210,7 +201,7 @@ else(GUI) endif(GUI) # Network -option(ENABLE_WEBSOCKET_INTERFACE "network websocket interface" ON) +option(ENABLE_WEBSOCKET_INTERFACE "network websocket interface" OFF) if(ENABLE_WEBSOCKET_INTERFACE) add_definitions(-DASIO_STANDALONE) set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) @@ -228,7 +219,7 @@ else(ENABLE_WEBSOCKET_INTERFACE) message(WARNING "WEBSOCKET_INTERFACE disabled.") endif(ENABLE_WEBSOCKET_INTERFACE) -option(ENABLE_LEGACY_NETWORK_INTERFACE "network xml interface (legacy)" ON) +option(ENABLE_LEGACY_NETWORK_INTERFACE "network xml interface (legacy)" OFF) if(ENABLE_LEGACY_NETWORK_INTERFACE) add_definitions(-DASIO_STANDALONE) set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) @@ -239,7 +230,7 @@ if(ENABLE_LEGACY_NETWORK_INTERFACE) include_directories(${PROJECT_SOURCE_DIR}/src/legacy_network) if(WIN32) - #add_definitions(-D_WIN32_WINNT=0x0601) # Windows 7 + add_definitions(-D_WIN32_WINNT=0x0601) # min Windows 7 list(APPEND LINKLIBS "-lws2_32 -lmswsock") endif(WIN32) message(STATUS "Enabled LEGACY_NETWORK interface") @@ -248,7 +239,7 @@ else(ENABLE_LEGACY_NETWORK_INTERFACE) endif(ENABLE_LEGACY_NETWORK_INTERFACE) # Head tracker -option(HEAD_TRACKER "Basic head tracker support" ON) +option(HEAD_TRACKER "Basic head tracker support" OFF) if(HEAD_TRACKER) list(APPEND SOURCE_FILES src/trackerrazor.cpp @@ -268,6 +259,8 @@ endif(HEAD_TRACKER) # Preprocessor symbols add_definitions(-DSSR_DATA_DIR="./data") +add_definitions(-DAPF_JACK_POLICY_DEBUG) +add_definitions(-DAPF_JACKCLIENT_DEBUG) # Config definitions # configure a header file to pass some of the CMake settings @@ -281,45 +274,45 @@ configure_file( # Compiler flags # Add a few for release builds (MAKE_BUILD_TYPE=RELEASE) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pipe -Wall -fomit-frame-pointer -ffast-math -funroll-loops -march=x86-64 -mmmx -msse -msse2 -mfpmath=sse") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -fomit-frame-pointer -ffast-math -funroll-loops -march=x86-64 -mmmx -msse -msse2 -mfpmath=sse") message(STATUS "Release Flags: " ${CMAKE_CXX_FLAGS_RELEASE}) # And for debug builds (MAKE_BUILD_TYPE=DEBUG) -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pipe -Wall -ffast-math -march=x86-64 -mmmx -msse -msse2 -mfpmath=sse -Weffc++") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wa,-mbig-obj") # -Weffc++ message(STATUS "Debug Flags: " ${CMAKE_CXX_FLAGS_DEBUG}) # Compile executables set(EXECUTABLES ssr-binaural - ssr-brs - ssr-vbap - ssr-wfs - ssr-aap - ssr-dca - ssr-generic +# ssr-brs +# ssr-vbap +# ssr-wfs +# ssr-aap +# ssr-dca +# ssr-generic ) add_executable(ssr-binaural src/ssr_binaural.cpp ${SOURCE_FILES}) -add_executable(ssr-brs src/ssr_brs.cpp ${SOURCE_FILES}) -add_executable(ssr-vbap src/ssr_vbap.cpp ${SOURCE_FILES}) -add_executable(ssr-wfs src/ssr_wfs.cpp ${SOURCE_FILES}) -add_executable(ssr-aap src/ssr_aap.cpp ${SOURCE_FILES}) -add_executable(ssr-dca src/ssr_dca.cpp ${SOURCE_FILES}) -add_executable(ssr-generic src/ssr_generic.cpp ${SOURCE_FILES}) +#add_executable(ssr-brs src/ssr_brs.cpp ${SOURCE_FILES}) +#add_executable(ssr-vbap src/ssr_vbap.cpp ${SOURCE_FILES}) +#add_executable(ssr-wfs src/ssr_wfs.cpp ${SOURCE_FILES}) +#add_executable(ssr-aap src/ssr_aap.cpp ${SOURCE_FILES}) +#add_executable(ssr-dca src/ssr_dca.cpp ${SOURCE_FILES}) +#add_executable(ssr-generic src/ssr_generic.cpp ${SOURCE_FILES}) # Link -if(WIN32) +if(NOT ${BUILD_SHARED_LIBS}) set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") -endif(WIN32) +endif() message(STATUS "Linking: " ${LINKLIBS} ${QT5PLATFORMSUPPORT_LIBS}) foreach(executable ${EXECUTABLES}) - target_link_libraries(${executable} Threads::Threads stdc++fs) + target_link_libraries(${executable} Threads::Threads) target_link_libraries(${executable} ${LINKLIBS}) if(GUI) target_link_libraries(${executable} Qt5::Gui Qt5::Core Qt5::Widgets Qt5::OpenGL ${QT5PLATFORMSUPPORT_LIBS}) - qt5_import_plugins(${executable} INCLUDE Qt5::Gui Qt5::Core Qt5::Widgets Qt5::OpenGL ${QT5PLATFORMSUPPORT_LIBS}) - qt5_import_plugins(${executable} INCLUDE_BY_TYPE platforms) - endif(GUI) endforeach(executable ${EXECUTABLES}) + + +# ../../mxe/tools/copydlldeps.sh --infile ./ssr-binaural.exe --destdir ./deps --recursivesrcdir ../../mxe/usr/x86_64-w64-mingw32.shared/ --srcdir ./ --copy --enforcedir ../../mxe/usr/x86_64-w64-mingw32.shared/qt5/plugins/platforms/ From 15d047b10cc5bd3f7499bc5daa26211bce3c34d0 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Thu, 16 Feb 2023 14:05:08 +0200 Subject: [PATCH 11/44] Update pathtools.h --- src/pathtools.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/pathtools.h b/src/pathtools.h index e0d00cfb..e932370a 100644 --- a/src/pathtools.h +++ b/src/pathtools.h @@ -82,6 +82,35 @@ inline std::string make_path_relative_to_current_dir(const std::string& path return fs::relative(fs::absolute(filename).parent_path() / p).string(); } +/** Cleanup @p in_path, e.g. by adjusting and removing duplicate separators. + * @param path A path given + * @return @p path in a canonical and native format. + **/ +inline std::string normalize_path(const std::string& in_path) { + fs::path p_canonical = fs::weakly_canonical(in_path); + std::string p_norm = p_canonical.make_preferred().string(); + return p_norm; +} + +/** Tries to find a home path, otherwise returns the root path. + * @return home path + **/ +inline fs::path get_home_dir() +{ + fs::path p_home = fs::current_path().root_path(); + char const* home = getenv("HOME"); + if (home) + { + p_home = fs::path(home); + } + home = getenv("USERPROFILE"); + if (home) + { + p_home = fs::path(home); + } + return p_home; +} + /** Insert escape characters (\) before whitespace characters. * @param filename the file name * @return the file name with escaped whitespace characters From cab8d4b57447b30cc7a6e01c11b273fdba38a08d Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Thu, 16 Feb 2023 14:05:14 +0200 Subject: [PATCH 12/44] Update configuration.cpp --- src/configuration.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index 71da4938..a1d7e097 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -193,12 +193,14 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) // load system-wide config file (Linux et al.) load_config_file("/etc/ssr.conf",conf); // load user config file (Mac) - std::string filename = getenv("HOME"); + std::string filename = pathtools::get_home_dir().string(); filename += "/Library/SoundScapeRenderer/ssr.conf"; + filename = pathtools::normalize_path(filename); load_config_file(filename.c_str(),conf); // load user config file (Linux et al.) - filename = getenv("HOME"); + filename = pathtools::get_home_dir().string(); filename += "/.ssr/ssr.conf"; + filename = pathtools::normalize_path(filename); load_config_file(filename.c_str(),conf); const std::string usage_string = @@ -629,6 +631,7 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) SSR_VERBOSE2(entry.first << " = " << entry.second); } + SSR_VERBOSE3("Done with parsing conf."); return conf; } From 9bb4ab1680aeebd1ea56c7ca9acb9f82e8c445bd Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 21 Feb 2023 18:19:16 +0200 Subject: [PATCH 13/44] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0f28c503..ca198e90 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,5 @@ src/config.h.in src/config.h _build/ bin/ - +ssr-win-bin/ *.exe From b9144e5e74d23f8c9c6cf88e8f7fba318265562a Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 21 Feb 2023 18:19:30 +0200 Subject: [PATCH 14/44] Update CMakeLists.txt --- CMakeLists.txt | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 84000b55..7f639c6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/_build) if(WIN32) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/ssr-win-bin) else(WIN32) - set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/src) + set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/ssr-bin) endif(WIN32) # Show the compiler @@ -64,7 +64,7 @@ set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) # TODO -find_package(PkgConfig REQUIRED) +#find_package(PkgConfig REQUIRED) if(WIN32) # Set Path to extern headers and libraries for Windows builds @@ -104,7 +104,9 @@ endif(WIN32) find_library(LIBSNDFILE_LIBRARY NAMES sndfile libsndfile-1) list(APPEND LINKLIBS ${LIBSNDFILE_LIBRARY}) -list(APPEND LINKLIBS -lFLAC -lopus -lvorbisenc -lvorbis -logg) +if(WIN32) + list(APPEND LINKLIBS -lFLAC -lopus -lvorbisenc -lvorbis -logg) +endif(WIN32) message(STATUS "Found SNDFILE: " ${LIBSNDFILE_LIBRARY}) option(ENABLE_ECASOUND "Ecasound soundfile playback/recording" OFF) @@ -135,7 +137,7 @@ list(APPEND LINKLIBS ${FFTWF_LIBRARY}) message(STATUS "Found FFTWF: " ${FFTWF_LIBRARY}) # GUI -option(GUI "Build GUI" OFF) +option(GUI "Build GUI" ON) if(GUI) # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -201,7 +203,7 @@ else(GUI) endif(GUI) # Network -option(ENABLE_WEBSOCKET_INTERFACE "network websocket interface" OFF) +option(ENABLE_WEBSOCKET_INTERFACE "network websocket interface" ON) if(ENABLE_WEBSOCKET_INTERFACE) add_definitions(-DASIO_STANDALONE) set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) @@ -219,8 +221,9 @@ else(ENABLE_WEBSOCKET_INTERFACE) message(WARNING "WEBSOCKET_INTERFACE disabled.") endif(ENABLE_WEBSOCKET_INTERFACE) -option(ENABLE_LEGACY_NETWORK_INTERFACE "network xml interface (legacy)" OFF) +option(ENABLE_LEGACY_NETWORK_INTERFACE "network xml interface (legacy)" ON) if(ENABLE_LEGACY_NETWORK_INTERFACE) + set(ENABLE_IP_INTERFACE ON) add_definitions(-DASIO_STANDALONE) set(ASIO_PATH ${PROJECT_SOURCE_DIR}/extern/include/asio/asio/include/) include_directories(${ASIO_PATH}) @@ -239,7 +242,7 @@ else(ENABLE_LEGACY_NETWORK_INTERFACE) endif(ENABLE_LEGACY_NETWORK_INTERFACE) # Head tracker -option(HEAD_TRACKER "Basic head tracker support" OFF) +option(HEAD_TRACKER "Basic head tracker support" ON) if(HEAD_TRACKER) list(APPEND SOURCE_FILES src/trackerrazor.cpp @@ -259,8 +262,8 @@ endif(HEAD_TRACKER) # Preprocessor symbols add_definitions(-DSSR_DATA_DIR="./data") -add_definitions(-DAPF_JACK_POLICY_DEBUG) -add_definitions(-DAPF_JACKCLIENT_DEBUG) +#add_definitions(-DAPF_JACK_POLICY_DEBUG) +#add_definitions(-DAPF_JACKCLIENT_DEBUG) # Config definitions # configure a header file to pass some of the CMake settings @@ -277,26 +280,26 @@ configure_file( set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -fomit-frame-pointer -ffast-math -funroll-loops -march=x86-64 -mmmx -msse -msse2 -mfpmath=sse") message(STATUS "Release Flags: " ${CMAKE_CXX_FLAGS_RELEASE}) # And for debug builds (MAKE_BUILD_TYPE=DEBUG) -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wa,-mbig-obj") # -Weffc++ +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra") # -Weffc++ -Wa,-mbig-obj message(STATUS "Debug Flags: " ${CMAKE_CXX_FLAGS_DEBUG}) # Compile executables set(EXECUTABLES ssr-binaural -# ssr-brs -# ssr-vbap -# ssr-wfs -# ssr-aap -# ssr-dca -# ssr-generic + ssr-brs + ssr-vbap + ssr-wfs + ssr-aap + ssr-dca + ssr-generic ) add_executable(ssr-binaural src/ssr_binaural.cpp ${SOURCE_FILES}) -#add_executable(ssr-brs src/ssr_brs.cpp ${SOURCE_FILES}) -#add_executable(ssr-vbap src/ssr_vbap.cpp ${SOURCE_FILES}) -#add_executable(ssr-wfs src/ssr_wfs.cpp ${SOURCE_FILES}) -#add_executable(ssr-aap src/ssr_aap.cpp ${SOURCE_FILES}) -#add_executable(ssr-dca src/ssr_dca.cpp ${SOURCE_FILES}) -#add_executable(ssr-generic src/ssr_generic.cpp ${SOURCE_FILES}) +add_executable(ssr-brs src/ssr_brs.cpp ${SOURCE_FILES}) +add_executable(ssr-vbap src/ssr_vbap.cpp ${SOURCE_FILES}) +add_executable(ssr-wfs src/ssr_wfs.cpp ${SOURCE_FILES}) +add_executable(ssr-aap src/ssr_aap.cpp ${SOURCE_FILES}) +add_executable(ssr-dca src/ssr_dca.cpp ${SOURCE_FILES}) +add_executable(ssr-generic src/ssr_generic.cpp ${SOURCE_FILES}) # Link From a54e7eda8de75aad512d25ea4489636ad3a48a7f Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 21 Feb 2023 18:19:32 +0200 Subject: [PATCH 15/44] Update generate_config.h.in --- generate_config.h.in | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/generate_config.h.in b/generate_config.h.in index 143e74a1..3dd910f9 100644 --- a/generate_config.h.in +++ b/generate_config.h.in @@ -2,34 +2,34 @@ /* graphical user interface (using Qt) */ -#cmakedefine ENABLE_GUI @ENABLE_GUI@ +#cmakedefine ENABLE_GUI /* separate control window */ -#cmakedefine ENABLE_FLOATING_CONTROL_PANEL @ENABLE_FLOATING_CONTROL_PANEL@ +#cmakedefine ENABLE_FLOATING_CONTROL_PANEL /* Ecasound soundfile playback/recording */ -#cmakedefine ENABLE_ECASOUND 0 +#cmakedefine ENABLE_ECASOUND /* XML network (TCP/IP) interface : LEGACY*/ -#cmakedefine ENABLE_IP_INTERFACE @ENABLE_LEGACY_NETWORK_INTERFACE@ +#cmakedefine ENABLE_IP_INTERFACE /* Websocket++ network (TCP/IP) interface : WEBSOCKET*/ -#cmakedefine ENABLE_WEBSOCKET_INTERFACE @ENABLE_WEBSOCKET_INTERFACE@ +#cmakedefine ENABLE_WEBSOCKET_INTERFACE /* Razor AHRS tracker support */ -#cmakedefine ENABLE_RAZOR @HEAD_TRACKER@ +#cmakedefine ENABLE_RAZOR /* Polhemus Fastrak/Patriot tracker support */ -#cmakedefine ENABLE_POLHEMUS @HEAD_TRACKER@ +#cmakedefine ENABLE_POLHEMUS /*?? support for isatty() ??*/ -#cmakedefine ENABLE_ISATTY 1 +#define ENABLE_ISATTY 1 /* Name of package */ #define PACKAGE "ssr" /* Version number of package */ -#define VERSION @SSR_VERSION@ +#define VERSION "@SSR_VERSION@" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "ssr@spatialaudio.net" @@ -50,10 +50,10 @@ #define PACKAGE_URL "http://spatialaudio.net/ssr/" /* List of SSR authors */ -#define SSR_AUTHORS "Written by:\n Matthias Geier, Jens Ahrens\nScientific supervision:\n Sascha Spors\nContributions by:\n Peter Bartz, Florian Hinterleitner, Torben Hohn,\n Lukas Kaser, André Möhl, Till Rettberg, Fiete Winter\nGUI design:\n Katharina Bredies, Jonas Loh, Jens Ahrens\nLogo design:\n Fabian Hemmert" +#define SSR_AUTHORS "Written by:\n Matthias Geier, Jens Ahrens\nScientific supervision:\n Sascha Spors\nContributions by:\n Peter Bartz, Florian Hinterleitner, Torben Hohn,\n Christoph Hohnerlein, Christoph Hold, Lukas Kaser, \n André Möhl, Till Rettberg, David Runge, Fiete Winter, \n IOhannes m zmölnig \nGUI design:\n Katharina Bredies, Jonas Loh, Jens Ahrens\nLogo design:\n Fabian Hemmert" /* List of SSR authors (with Qt markup) */ -#define SSR_AUTHORS_QT "Written by:
 Matthias Geier, Jens Ahrens

Scientific supervision:
 Sascha Spors

Contributions by:
 Peter Bartz, Florian Hinterleitner, Torben Hohn,
 Lukas Kaser, André Möhl, Till Rettberg, Fiete Winter

GUI design:
 Katharina Bredies, Jonas Loh, Jens Ahrens

Logo design:
 Fabian Hemmert" +#define SSR_AUTHORS_QT "The SSR Authors." /* SSR copyright notice */ #define SSR_COPYRIGHT "Copyright © 2016 Division of Applied Acoustics, Chalmers University of Technology\nCopyright © 2014 Institut für Nachrichtentechnik, Universität Rostock\nCopyright © 2012 Quality & Usability Lab, Telekom Innovation Laboratories, TU Berlin\n\nLicense GPLv3+: GNU GPL version 3 or later \nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law." From 5fd622e55ee10749b7abb79a5489ffc17a0d3d3f Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 21 Feb 2023 18:20:12 +0200 Subject: [PATCH 16/44] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ca198e90..7c917002 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,6 @@ src/config.h.in src/config.h _build/ bin/ +ssr-bin/ ssr-win-bin/ *.exe From 1a33eee82fc98fc6ff959680215ea604d9850656 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 21 Feb 2023 18:20:32 +0200 Subject: [PATCH 17/44] More Verbose --- src/binauralrenderer.h | 1 + src/ssr_main.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/binauralrenderer.h b/src/binauralrenderer.h index b7a7e257..25c5df0b 100644 --- a/src/binauralrenderer.h +++ b/src/binauralrenderer.h @@ -134,6 +134,7 @@ BinauralRenderer::_load_hrtfs(const std::string& filename, size_t size) auto idx = filename.find_last_of("."); if (idx != std::string::npos) { + SSR_VERBOSE3("Loading HRTFS"); auto ext = filename.substr(idx + 1); std::transform(ext.begin(), ext.end(), ext.begin() , [](unsigned char c){ return std::tolower(c); }); diff --git a/src/ssr_main.h b/src/ssr_main.h index 3c7f6b62..f9f9c550 100644 --- a/src/ssr_main.h +++ b/src/ssr_main.h @@ -49,6 +49,7 @@ int main(int argc, char* argv[]) std::signal(SIGTERM, signal_handler); try { + SSR_VERBOSE3("STARTING SSR"); // NB: This is static to be cleaned up automatically when exit() is called. static ssr::Controller controller{argc, argv}; controller.run(); From 986b4fa64ffbec5ad61cb19fa47fe37055ecd5ff Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 21 Feb 2023 18:21:08 +0200 Subject: [PATCH 18/44] QT_STATIC handling --- src/gui/qgui.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/qgui.h b/src/gui/qgui.h index e4f1dccb..fd6a49d4 100644 --- a/src/gui/qgui.h +++ b/src/gui/qgui.h @@ -33,6 +33,12 @@ #include #include #include +#ifdef _WIN32 +#ifdef STATIC_QT +#include +Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) // for static build +#endif // STATIC_QT +#endif // _WIN32 #include "quserinterface.h" #include "scene.h" From 02f6b06fe90195e68666db7a3ca14562106c6537 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 21 Feb 2023 18:22:01 +0200 Subject: [PATCH 19/44] Make path handling cross platform --- src/gui/qgui.cpp | 4 +++- src/pathtools.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/qgui.cpp b/src/gui/qgui.cpp index cdc2aaa0..63f17c40 100644 --- a/src/gui/qgui.cpp +++ b/src/gui/qgui.cpp @@ -203,7 +203,9 @@ ssr::QGUI::QGUI(api::Publisher& controller, const LegacyScene& scene, int &argc, , path_to_gui_images, path_to_scene_menu) { // this is a quick hack to allow dynamic specification of path - qt_style_sheet.replace(QString("images"), QString( path_to_gui_images.c_str() )); + QString url_to_gui_images = path_to_gui_images.c_str(); + url_to_gui_images.replace(QString("\\"), "/"); // url needs all forward + qt_style_sheet.replace(QString("images"), url_to_gui_images); // set stylesheet _qt_app.setStyleSheet(qt_style_sheet); diff --git a/src/pathtools.h b/src/pathtools.h index e932370a..bcf17456 100644 --- a/src/pathtools.h +++ b/src/pathtools.h @@ -79,7 +79,7 @@ inline std::string make_path_relative_to_current_dir(const std::string& path { return p.string(); } - return fs::relative(fs::absolute(filename).parent_path() / p).string(); + return fs::relative(fs::absolute(filename).parent_path() / p).make_preferred().string(); } /** Cleanup @p in_path, e.g. by adjusting and removing duplicate separators. From 1c6bf8da6b26b6d0e90135a396de93b6c3a8d6f5 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 28 Feb 2023 19:05:19 +0200 Subject: [PATCH 20/44] Extend pathtools cross-platform --- src/configuration.cpp | 6 ++++-- src/controller.h | 6 +++--- src/gui/qgui.cpp | 4 +++- src/pathtools.h | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index 71da4938..115a3234 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -193,12 +193,14 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) // load system-wide config file (Linux et al.) load_config_file("/etc/ssr.conf",conf); // load user config file (Mac) - std::string filename = getenv("HOME"); + std::string filename = pathtools::get_home_dir().string(); filename += "/Library/SoundScapeRenderer/ssr.conf"; + filename = pathtools::normalize_path(filename); load_config_file(filename.c_str(),conf); // load user config file (Linux et al.) - filename = getenv("HOME"); + filename = pathtools::get_home_dir().string(); filename += "/.ssr/ssr.conf"; + filename = pathtools::normalize_path(filename); load_config_file(filename.c_str(),conf); const std::string usage_string = diff --git a/src/controller.h b/src/controller.h index 3b5d4053..d83b0ac8 100644 --- a/src/controller.h +++ b/src/controller.h @@ -1526,7 +1526,7 @@ Controller::_load_scene(const std::string& scene_file_name) return true; } - std::string file_extension = fs::path(scene_file_name).extension(); + std::string file_extension = fs::path(scene_file_name).extension().string(); if (file_extension == "") { @@ -2307,7 +2307,7 @@ Controller::_add_sources(Node& node { _add_audio_file_name(source_node , pathtools::make_path_relative_to_file(source.audio_file_name - , scene_file_name), source.audio_file_channel); + , scene_file_name).string(), source.audio_file_channel); } } @@ -2341,7 +2341,7 @@ Controller::_add_sources(Node& node { source_node.new_attribute("properties-file" , pathtools::make_path_relative_to_file(source.properties_file - , scene_file_name)); + , scene_file_name).string()); } }); } diff --git a/src/gui/qgui.cpp b/src/gui/qgui.cpp index cdc2aaa0..63f17c40 100644 --- a/src/gui/qgui.cpp +++ b/src/gui/qgui.cpp @@ -203,7 +203,9 @@ ssr::QGUI::QGUI(api::Publisher& controller, const LegacyScene& scene, int &argc, , path_to_gui_images, path_to_scene_menu) { // this is a quick hack to allow dynamic specification of path - qt_style_sheet.replace(QString("images"), QString( path_to_gui_images.c_str() )); + QString url_to_gui_images = path_to_gui_images.c_str(); + url_to_gui_images.replace(QString("\\"), "/"); // url needs all forward + qt_style_sheet.replace(QString("images"), url_to_gui_images); // set stylesheet _qt_app.setStyleSheet(qt_style_sheet); diff --git a/src/pathtools.h b/src/pathtools.h index a7677b4e..b61e322d 100644 --- a/src/pathtools.h +++ b/src/pathtools.h @@ -77,9 +77,38 @@ inline std::string make_path_relative_to_current_dir(const std::string& path auto p = fs::path{path}; if (p.is_absolute() || p == "") { - return p; + return p.make_preferred().string(); + } + return fs::relative(fs::absolute(filename).parent_path() / p).make_preferred().string(); +} + +/** Cleanup @p path, e.g. by adjusting and removing duplicate separators. + * @param path A path given + * @return @p path in a canonical and native format. + **/ +inline std::string normalize_path(const std::string& path) { + fs::path p_canonical = fs::weakly_canonical(path); + std::string p_norm = p_canonical.make_preferred().string(); + return p_norm; +} + +/** Tries to find a home path, otherwise returns the root path. + * @return home path + **/ +inline fs::path get_home_dir() +{ + fs::path p_home = fs::current_path().root_path(); + char const* home = getenv("HOME"); + if (home) + { + p_home = fs::path(home); + } + home = getenv("USERPROFILE"); + if (home) + { + p_home = fs::path(home); } - return fs::relative(fs::absolute(filename).parent_path() / p).string(); + return p_home; } /** Insert escape characters (\) before whitespace characters. From 08a8686c78ec866ab902ad1d0523e0fe282701ff Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Wed, 1 Mar 2023 14:22:56 +0100 Subject: [PATCH 21/44] CI: drop support for gcc 8 --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9c61b15e..ebad1420 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,10 +11,10 @@ jobs: CC: gcc-12 CXX: g++-12 - os: ubuntu-20.04 - compiler-pkg: g++-8 + compiler-pkg: g++-9 env: - CC: gcc-8 - CXX: g++-8 + CC: gcc-9 + CXX: g++-9 - os: ubuntu-22.04 compiler-pkg: clang-14 env: From c839465a20493490a5058d3b33e29b115fe3691b Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 13 Mar 2023 11:07:23 +0200 Subject: [PATCH 22/44] Simplify home handling --- src/configuration.cpp | 14 ++++++-------- src/pathtools.h | 11 +++++------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index 115a3234..a645fdf8 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -193,15 +193,13 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) // load system-wide config file (Linux et al.) load_config_file("/etc/ssr.conf",conf); // load user config file (Mac) - std::string filename = pathtools::get_home_dir().string(); - filename += "/Library/SoundScapeRenderer/ssr.conf"; - filename = pathtools::normalize_path(filename); - load_config_file(filename.c_str(),conf); + fs::path home_dir = pathtools::get_home_dir(); + fs::path conf_file; + conf_file = pathtools::normalize_path(home_dir / "Library/SoundScapeRenderer/ssr.conf"); + load_config_file(conf_file.c_str(),conf); // load user config file (Linux et al.) - filename = pathtools::get_home_dir().string(); - filename += "/.ssr/ssr.conf"; - filename = pathtools::normalize_path(filename); - load_config_file(filename.c_str(),conf); + conf_file = pathtools::normalize_path(home_dir / ".ssr/ssr.conf"); + load_config_file(conf_file.c_str(),conf); const std::string usage_string = "Usage: " + std::string(conf.exec_name) + " [OPTIONS] \n"; diff --git a/src/pathtools.h b/src/pathtools.h index b61e322d..ce2563d2 100644 --- a/src/pathtools.h +++ b/src/pathtools.h @@ -92,23 +92,22 @@ inline std::string normalize_path(const std::string& path) { return p_norm; } -/** Tries to find a home path, otherwise returns the root path. +/** Tries to find a home path, otherwise returns the current path. * @return home path **/ inline fs::path get_home_dir() { - fs::path p_home = fs::current_path().root_path(); - char const* home = getenv("HOME"); + const char* home = getenv("HOME"); if (home) { - p_home = fs::path(home); + return fs::path{home}; } home = getenv("USERPROFILE"); if (home) { - p_home = fs::path(home); + return fs::path{home}; } - return p_home; + return fs::current_path(); } /** Insert escape characters (\) before whitespace characters. From 3e9b505337df17a8fa091ba5e090a024e832f004 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 13 Mar 2023 11:07:23 +0200 Subject: [PATCH 23/44] Simplify home handling --- src/configuration.cpp | 14 ++++++-------- src/pathtools.h | 11 +++++------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index a1d7e097..3c009f76 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -193,15 +193,13 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) // load system-wide config file (Linux et al.) load_config_file("/etc/ssr.conf",conf); // load user config file (Mac) - std::string filename = pathtools::get_home_dir().string(); - filename += "/Library/SoundScapeRenderer/ssr.conf"; - filename = pathtools::normalize_path(filename); - load_config_file(filename.c_str(),conf); + fs::path home_dir = pathtools::get_home_dir(); + fs::path conf_file; + conf_file = pathtools::normalize_path(home_dir / "Library/SoundScapeRenderer/ssr.conf"); + load_config_file(conf_file.c_str(),conf); // load user config file (Linux et al.) - filename = pathtools::get_home_dir().string(); - filename += "/.ssr/ssr.conf"; - filename = pathtools::normalize_path(filename); - load_config_file(filename.c_str(),conf); + conf_file = pathtools::normalize_path(home_dir / ".ssr/ssr.conf"); + load_config_file(conf_file.c_str(),conf); const std::string usage_string = "Usage: " + std::string(conf.exec_name) + " [OPTIONS] \n"; diff --git a/src/pathtools.h b/src/pathtools.h index bcf17456..b24f7469 100644 --- a/src/pathtools.h +++ b/src/pathtools.h @@ -92,23 +92,22 @@ inline std::string normalize_path(const std::string& in_path) { return p_norm; } -/** Tries to find a home path, otherwise returns the root path. +/** Tries to find a home path, otherwise returns the current path. * @return home path **/ inline fs::path get_home_dir() { - fs::path p_home = fs::current_path().root_path(); - char const* home = getenv("HOME"); + const char* home = getenv("HOME"); if (home) { - p_home = fs::path(home); + return fs::path{home}; } home = getenv("USERPROFILE"); if (home) { - p_home = fs::path(home); + return fs::path{home}; } - return p_home; + return fs::current_path(); } /** Insert escape characters (\) before whitespace characters. From 7f3fa849d4225af90221ec543fa16b1c8f1fca15 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 13 Mar 2023 11:16:01 +0200 Subject: [PATCH 24/44] Avoid implicit string conversion --- src/configuration.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index 3c009f76..7f7c2c0e 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -193,12 +193,12 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) // load system-wide config file (Linux et al.) load_config_file("/etc/ssr.conf",conf); // load user config file (Mac) - fs::path home_dir = pathtools::get_home_dir(); - fs::path conf_file; - conf_file = pathtools::normalize_path(home_dir / "Library/SoundScapeRenderer/ssr.conf"); + std::string home_dir = pathtools::get_home_dir().string(); + std::string conf_file; + conf_file = pathtools::normalize_path(home_dir + "/Library/SoundScapeRenderer/ssr.conf"); load_config_file(conf_file.c_str(),conf); // load user config file (Linux et al.) - conf_file = pathtools::normalize_path(home_dir / ".ssr/ssr.conf"); + conf_file = pathtools::normalize_path(home_dir + "/.ssr/ssr.conf"); load_config_file(conf_file.c_str(),conf); const std::string usage_string = From b9c4a3b9a9f5b446c54f74923bde3facf84793f0 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 13 Mar 2023 11:16:01 +0200 Subject: [PATCH 25/44] Avoid implicit string conversion --- src/configuration.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index a645fdf8..704f05d8 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -193,12 +193,12 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) // load system-wide config file (Linux et al.) load_config_file("/etc/ssr.conf",conf); // load user config file (Mac) - fs::path home_dir = pathtools::get_home_dir(); - fs::path conf_file; - conf_file = pathtools::normalize_path(home_dir / "Library/SoundScapeRenderer/ssr.conf"); + std::string home_dir = pathtools::get_home_dir().string(); + std::string conf_file; + conf_file = pathtools::normalize_path(home_dir + "/Library/SoundScapeRenderer/ssr.conf"); load_config_file(conf_file.c_str(),conf); // load user config file (Linux et al.) - conf_file = pathtools::normalize_path(home_dir / ".ssr/ssr.conf"); + conf_file = pathtools::normalize_path(home_dir + "/.ssr/ssr.conf"); load_config_file(conf_file.c_str(),conf); const std::string usage_string = From e08f20e332fea9f24cae49f1e15d463e08ec7598 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 20 Mar 2023 17:18:31 +0200 Subject: [PATCH 26/44] return path() if failing to find home_path --- src/pathtools.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pathtools.h b/src/pathtools.h index ce2563d2..ea723d03 100644 --- a/src/pathtools.h +++ b/src/pathtools.h @@ -92,7 +92,7 @@ inline std::string normalize_path(const std::string& path) { return p_norm; } -/** Tries to find a home path, otherwise returns the current path. +/** Tries to find a home path, otherwise returns path(). * @return home path **/ inline fs::path get_home_dir() @@ -107,7 +107,7 @@ inline fs::path get_home_dir() { return fs::path{home}; } - return fs::current_path(); + return fs::path(); } /** Insert escape characters (\) before whitespace characters. From fd296510d20916b1874c0ad4da2e0ccf8908a979 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 20 Mar 2023 17:19:13 +0200 Subject: [PATCH 27/44] Use fs::path for conf_file --- src/configuration.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index 7f7c2c0e..a8288d85 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -193,13 +193,13 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) // load system-wide config file (Linux et al.) load_config_file("/etc/ssr.conf",conf); // load user config file (Mac) - std::string home_dir = pathtools::get_home_dir().string(); - std::string conf_file; - conf_file = pathtools::normalize_path(home_dir + "/Library/SoundScapeRenderer/ssr.conf"); - load_config_file(conf_file.c_str(),conf); + fs::path home_dir = pathtools::get_home_dir(); + fs::path conf_file; + conf_file = home_dir / "Library/SoundScapeRenderer/ssr.conf"; + load_config_file(conf_file.make_preferred().string().c_str(),conf); // load user config file (Linux et al.) - conf_file = pathtools::normalize_path(home_dir + "/.ssr/ssr.conf"); - load_config_file(conf_file.c_str(),conf); + conf_file = home_dir / ".ssr/ssr.conf"; + load_config_file(conf_file.make_preferred().string().c_str(),conf); const std::string usage_string = "Usage: " + std::string(conf.exec_name) + " [OPTIONS] \n"; From 12c4c1ab69f00adeaf62fecca9967d03ec8bfec7 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 30 May 2023 17:52:34 +0300 Subject: [PATCH 28/44] Start installer --- installer.nsi | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 installer.nsi diff --git a/installer.nsi b/installer.nsi new file mode 100644 index 00000000..c7c6e9a5 --- /dev/null +++ b/installer.nsi @@ -0,0 +1,57 @@ +# define name of installer +OutFile "SSR-installer.exe" + +# The default installation directory +InstallDir $PROGRAMFILES64\SSR + +RequestExecutionLevel admin + +;-------------------------------- +Page directory +Page instfiles + +UninstPage uninstConfirm +UninstPage instfiles +;------------------------------- + + +# start default section +Section "Installer Section" + + # set the installation directory as the destination for the following actions + SetOutPath $INSTDIR + + # specify file to go in output path + File ssr-win-bin\*.exe + + # add dependencies + File /r /x libjack*.dll ssr-win-bin\deps\*.* + + # add resources + File /r ssr-win-bin\data\ + + File /oname=data\default_hrirs.wav ssr-win-bin\data\impulse_responses\hrirs\hrirs_fabian_min_phase_eq.wav + + # create the uninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + +SectionEnd + +Section "Start Menu Shortcuts (required)" + # create a shortcut named "SSR" in the start menu programs directory + # point the new shortcut at the program uninstaller + CreateShortcut "$SMPROGRAMS\SoundScapeRenderer(SSR)\uninstall.lnk" "$INSTDIR\uninstall.exe" +SectionEnd + + +# uninstaller section start +Section "un.Uninstaller Section" + # TODO + + # Remove the link from the start menu + Delete "$SMPROGRAMS\SoundScapeRenderer(SSR)\uninstall.lnk" + + RMDir "$SMPROGRAMS\SoundScapeRenderer(SSR)" + RMDir $INSTDIR +# uninstaller section end +SectionEnd \ No newline at end of file From 7a2b04ab26e13476cfe5f3880461b7ca83d8c621 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Thu, 1 Jun 2023 16:39:55 +0300 Subject: [PATCH 29/44] rename installer and update --- installer.nsi => SSR-installer.nsi | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) rename installer.nsi => SSR-installer.nsi (79%) diff --git a/installer.nsi b/SSR-installer.nsi similarity index 79% rename from installer.nsi rename to SSR-installer.nsi index c7c6e9a5..d496a5e5 100644 --- a/installer.nsi +++ b/SSR-installer.nsi @@ -2,7 +2,7 @@ OutFile "SSR-installer.exe" # The default installation directory -InstallDir $PROGRAMFILES64\SSR +InstallDir $PROGRAMFILES64\SoundScapeRenderer RequestExecutionLevel admin @@ -40,7 +40,7 @@ SectionEnd Section "Start Menu Shortcuts (required)" # create a shortcut named "SSR" in the start menu programs directory # point the new shortcut at the program uninstaller - CreateShortcut "$SMPROGRAMS\SoundScapeRenderer(SSR)\uninstall.lnk" "$INSTDIR\uninstall.exe" + CreateShortcut "$SMPROGRAMS\SoundScapeRenderer\uninstall.lnk" "$INSTDIR\uninstall.exe" SectionEnd @@ -49,9 +49,12 @@ Section "un.Uninstaller Section" # TODO # Remove the link from the start menu - Delete "$SMPROGRAMS\SoundScapeRenderer(SSR)\uninstall.lnk" + Delete "$SMPROGRAMS\SoundScapeRenderer\uninstall.lnk" - RMDir "$SMPROGRAMS\SoundScapeRenderer(SSR)" + RMDir "$SMPROGRAMS\SoundScapeRenderer" RMDir $INSTDIR + + MessageBox MB_OK "You need to manually remove the files for now!" + # uninstaller section end SectionEnd \ No newline at end of file From 032c33a73cbe10931a0a23ed535ac7358fde4da9 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Thu, 1 Jun 2023 16:57:58 +0300 Subject: [PATCH 30/44] Update build --- CMakeLists.txt | 124 ++++++++++++++++++++++++++++++------------- generate_config.h.in | 9 ++++ 2 files changed, 96 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f639c6b..9007fb7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,9 +33,22 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(SOURCE_FILES + src/configuration.cpp + src/ssr_global.cpp + src/xmlparser.cpp + src/legacy_directionalpoint.cpp + src/legacy_orientation.cpp + src/legacy_position.cpp + src/legacy_scene.cpp + ) + + # The following folders will be included include_directories(${PROJECT_SOURCE_DIR}/src) +# Dependencies + # Include APF set(APF_PATH ${PROJECT_SOURCE_DIR}/apf) include_directories(${APF_PATH}) @@ -44,20 +57,9 @@ include_directories(${APF_PATH}) set(GML_PATH ${PROJECT_SOURCE_DIR}/gml/include) include_directories(${GML_PATH}) -# Files -set(SOURCE_FILES - src/configuration.cpp - src/ssr_global.cpp - src/xmlparser.cpp - src/legacy_directionalpoint.cpp - src/legacy_orientation.cpp - src/legacy_position.cpp - src/legacy_scene.cpp - ) -# Libraries -# Add libraries to LINKLIBS -set(LINKLIBS) +# Add libraries to EXTRA_LIBS +set(EXTRA_LIBS) #set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) @@ -91,21 +93,21 @@ if(WIN32) endif() find_package(LibXml2 REQUIRED) include_directories(${LIBXML2_INCLUDE_DIR}) - list(APPEND LINKLIBS ${LIBXML2_LIBRARY}) - #list(APPEND LINKLIBS "-lxml2 -lz -llzma -lws2_32") - list(APPEND LINKLIBS "-llzma -lz") + list(APPEND EXTRA_LIBS ${LIBXML2_LIBRARY}) + #list(APPEND EXTRA_LIBS "-lxml2 -lz -llzma -lws2_32") + list(APPEND EXTRA_LIBS "-llzma -lz") message(STATUS "Found XML2: " ${LIBXML2_LIBRARY}) message(STATUS "Found XML2 headers: " ${LIBXML2_INCLUDE_DIR}) else(WIN32) find_package(LibXml2 REQUIRED) include_directories(${LIBXML2_INCLUDE_DIR}) - list(APPEND LINKLIBS ${LIBXML2_LIBRARY}) + list(APPEND EXTRA_LIBS ${LIBXML2_LIBRARY}) endif(WIN32) find_library(LIBSNDFILE_LIBRARY NAMES sndfile libsndfile-1) -list(APPEND LINKLIBS ${LIBSNDFILE_LIBRARY}) +list(APPEND EXTRA_LIBS ${LIBSNDFILE_LIBRARY}) if(WIN32) - list(APPEND LINKLIBS -lFLAC -lopus -lvorbisenc -lvorbis -logg) + list(APPEND EXTRA_LIBS -lFLAC -lopus -lvorbisenc -lvorbis -logg) endif(WIN32) message(STATUS "Found SNDFILE: " ${LIBSNDFILE_LIBRARY}) @@ -118,22 +120,22 @@ if(ENABLE_ECASOUND) find_path(ECASOUND_INCLUDE_DIR NAMES ecasoundc.h HINTS /usr/include/libecasoundc) include_directories(${ECASOUND_INCLUDE_DIR}) find_library(ECASOUND_LIBRARY NAMES ecasoundc) - list(APPEND LINKLIBS ${ECASOUND_LIBRARY}) + list(APPEND EXTRA_LIBS ${ECASOUND_LIBRARY}) message(STATUS "Found ECASOUND: " ${ECASOUND_LIBRARY}) else(ENABLE_ECASOUND) message(WARNING "ECASOUND disabled.") endif(ENABLE_ECASOUND) find_library(JACK_LIBRARY NAMES jack libjack64) -list(APPEND LINKLIBS ${JACK_LIBRARY}) +list(APPEND EXTRA_LIBS ${JACK_LIBRARY}) message(STATUS "Found JACK :" ${JACK_LIBRARY}) find_library(FFTW_LIBRARY NAMES fftw3 libfftw3-3) -list(APPEND LINKLIBS ${FFTW_LIBRARY}) +list(APPEND EXTRA_LIBS ${FFTW_LIBRARY}) message(STATUS "Found FFTW: " ${FFTW_LIBRARY}) find_library(FFTWF_LIBRARY NAMES fftw3f libfftw3f-3) -list(APPEND LINKLIBS ${FFTWF_LIBRARY}) +list(APPEND EXTRA_LIBS ${FFTWF_LIBRARY}) message(STATUS "Found FFTWF: " ${FFTWF_LIBRARY}) # GUI @@ -193,8 +195,8 @@ if(GUI) # OpenGL find_package(OpenGL REQUIRED) include_directories(${OPENGL_INCLUDE_DIR}) - list(APPEND LINKLIBS ${OPENGL_gl_LIBRARY}) - list(APPEND LINKLIBS ${OPENGL_glu_LIBRARY}) + list(APPEND EXTRA_LIBS ${OPENGL_gl_LIBRARY}) + list(APPEND EXTRA_LIBS ${OPENGL_glu_LIBRARY}) message(STATUS "Build GUI") @@ -233,8 +235,8 @@ if(ENABLE_LEGACY_NETWORK_INTERFACE) include_directories(${PROJECT_SOURCE_DIR}/src/legacy_network) if(WIN32) - add_definitions(-D_WIN32_WINNT=0x0601) # min Windows 7 - list(APPEND LINKLIBS "-lws2_32 -lmswsock") + #add_definitions(-D_WIN32_WINNT=0x0601) # min Windows 7, conflict VRPN + list(APPEND EXTRA_LIBS "-lws2_32 -lmswsock") endif(WIN32) message(STATUS "Enabled LEGACY_NETWORK interface") else(ENABLE_LEGACY_NETWORK_INTERFACE) @@ -255,11 +257,53 @@ if(HEAD_TRACKER) add_definitions(-DENABLE_O_NDELAY_WORKAROUND) # bits/fcntl2.h endif(WIN32) message(STATUS "Basic head tracker support") + + option(VRPN "VRPN tracker support" ON) + if(VRPN) + message(STATUS "Adding VRPN:") + list(APPEND SOURCE_FILES + src/trackervrpn.cpp + ) + set(VRPN_BUILD_CLIENT_LIBRARY TRUE CACHE INTERNAL "" FORCE) + #add_definitions(-D_TIMEZONE_DEFINED) # hack + add_subdirectory(vrpn) + include_directories(vrpn) + list(APPEND EXTRA_LIBS vrpn) + set(ENABLE_VRPN ON) + message(STATUS "VRPN head tracker support") + endif(VRPN) + option(INTERSENSE "INTERSENSE tracker support" OFF) + if(INTERSENSE) + add_definitions(-DHAVE_INTERSENSE_404) + list(APPEND SOURCE_FILES + src/trackerintersense.cpp + ) + include_directories(intersense) + list(APPEND EXTRA_LIBS isense) + set(ENABLE_INTERSENSE ON) + message(STATUS "INTERSENSE head tracker support") + endif(INTERSENSE) else(HEAD_TRACKER) message(WARNING "HEAD_TRACKER disabled.") endif(HEAD_TRACKER) +# SOFA support +option(SOFA "SOFA file support" ON) +if(SOFA) + message(STATUS "Adding SOFA:") + option(BUILD_TESTS OFF) + add_subdirectory(libmysofa) + include_directories(libmysofa/src/hrtf) + if(${BUILD_SHARED_LIBS}) + list(APPEND EXTRA_LIBS mysofa-shared) + else() + list(APPEND EXTRA_LIBS mysofa-static) + endif() + set(ENABLE_SOFA ON) + message(STATUS "SOFA file support") +endif(SOFA) + # Preprocessor symbols add_definitions(-DSSR_DATA_DIR="./data") #add_definitions(-DAPF_JACK_POLICY_DEBUG) @@ -293,13 +337,13 @@ set(EXECUTABLES ssr-dca ssr-generic ) -add_executable(ssr-binaural src/ssr_binaural.cpp ${SOURCE_FILES}) -add_executable(ssr-brs src/ssr_brs.cpp ${SOURCE_FILES}) -add_executable(ssr-vbap src/ssr_vbap.cpp ${SOURCE_FILES}) -add_executable(ssr-wfs src/ssr_wfs.cpp ${SOURCE_FILES}) -add_executable(ssr-aap src/ssr_aap.cpp ${SOURCE_FILES}) -add_executable(ssr-dca src/ssr_dca.cpp ${SOURCE_FILES}) -add_executable(ssr-generic src/ssr_generic.cpp ${SOURCE_FILES}) +add_executable(ssr-binaural src/ssr_binaural.cpp) +add_executable(ssr-brs src/ssr_brs.cpp) +add_executable(ssr-vbap src/ssr_vbap.cpp) +add_executable(ssr-wfs src/ssr_wfs.cpp) +add_executable(ssr-aap src/ssr_aap.cpp) +add_executable(ssr-dca src/ssr_dca.cpp) +add_executable(ssr-generic src/ssr_generic.cpp) # Link @@ -307,15 +351,21 @@ if(NOT ${BUILD_SHARED_LIBS}) set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") endif() -message(STATUS "Linking: " ${LINKLIBS} ${QT5PLATFORMSUPPORT_LIBS}) +message(STATUS "Linking: " ${EXTRA_LIBS} ${QT5PLATFORMSUPPORT_LIBS}) foreach(executable ${EXECUTABLES}) + target_sources(${executable} + PRIVATE + ${SOURCE_FILES} + ) target_link_libraries(${executable} Threads::Threads) - target_link_libraries(${executable} ${LINKLIBS}) + target_link_libraries(${executable} ${EXTRA_LIBS}) if(GUI) target_link_libraries(${executable} Qt5::Gui Qt5::Core Qt5::Widgets Qt5::OpenGL ${QT5PLATFORMSUPPORT_LIBS}) endif(GUI) endforeach(executable ${EXECUTABLES}) -# ../../mxe/tools/copydlldeps.sh --infile ./ssr-binaural.exe --destdir ./deps --recursivesrcdir ../../mxe/usr/x86_64-w64-mingw32.shared/ --srcdir ./ --copy --enforcedir ../../mxe/usr/x86_64-w64-mingw32.shared/qt5/plugins/platforms/ +# x86_64-w64-mingw32.shared.posix-cmake -S . -B _build/ -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON +# x86_64-w64-mingw32.shared.posix-cmake --build ./_build -j4 +# ../mxe/tools/copydlldeps.sh --indir ./ssr-win-bin --destdir ./ssr-win-bin/deps --recursivesrcdir ../mxe/usr/x86_64-w64-mingw32.shared/ --srcdir ./_build --copy --enforcedir ./_build/*.dll --enforcedir ../mxe/usr/x86_64-w64-mingw32.shared/qt5/plugins/platforms/ diff --git a/generate_config.h.in b/generate_config.h.in index 3dd910f9..31fde76e 100644 --- a/generate_config.h.in +++ b/generate_config.h.in @@ -22,6 +22,15 @@ /* Polhemus Fastrak/Patriot tracker support */ #cmakedefine ENABLE_POLHEMUS +/* VRPN head tracker support */ +#cmakedefine ENABLE_VRPN + +/* INTERSENSE tracker support */ +#cmakedefine ENABLE_INTERSENSE + +/* SOFA file support */ +#cmakedefine ENABLE_SOFA + /*?? support for isatty() ??*/ #define ENABLE_ISATTY 1 From 1bf1ea99c21aa269bec107f8f62866dbdb65724a Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Fri, 2 Jun 2023 17:51:15 +0300 Subject: [PATCH 31/44] Cleanup CMAKELISTS --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9007fb7f..3df97d21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,7 +265,6 @@ if(HEAD_TRACKER) src/trackervrpn.cpp ) set(VRPN_BUILD_CLIENT_LIBRARY TRUE CACHE INTERNAL "" FORCE) - #add_definitions(-D_TIMEZONE_DEFINED) # hack add_subdirectory(vrpn) include_directories(vrpn) list(APPEND EXTRA_LIBS vrpn) From 25dd0db6e1986e398ccb0c222580da9522582ac2 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Fri, 2 Jun 2023 17:51:29 +0300 Subject: [PATCH 32/44] Add Shortcut to installer --- SSR-installer.nsi | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/SSR-installer.nsi b/SSR-installer.nsi index d496a5e5..533ddfc0 100644 --- a/SSR-installer.nsi +++ b/SSR-installer.nsi @@ -7,6 +7,7 @@ InstallDir $PROGRAMFILES64\SoundScapeRenderer RequestExecutionLevel admin ;-------------------------------- +Page components Page directory Page instfiles @@ -37,10 +38,12 @@ Section "Installer Section" SectionEnd -Section "Start Menu Shortcuts (required)" - # create a shortcut named "SSR" in the start menu programs directory +Section "Start Menu Shortcuts" + # create a shortcut named "SoundScapeRenderer" in the start menu programs directory # point the new shortcut at the program uninstaller + CreateDirectory "$SMPROGRAMS\SoundScapeRenderer" CreateShortcut "$SMPROGRAMS\SoundScapeRenderer\uninstall.lnk" "$INSTDIR\uninstall.exe" + SectionEnd From e1d943ed9b04bf76683124d26aa99b56c139a051 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Fri, 2 Jun 2023 18:11:39 +0300 Subject: [PATCH 33/44] Update README --- README | 20 ------- README.md | 60 +++++++++++++++++++ doc/manual/images/screenshot_jack.png | Bin 0 -> 22313 bytes doc/manual/images/screenshot_ssr-windows.png | Bin 0 -> 43045 bytes 4 files changed, 60 insertions(+), 20 deletions(-) delete mode 100644 README create mode 100644 README.md create mode 100644 doc/manual/images/screenshot_jack.png create mode 100644 doc/manual/images/screenshot_ssr-windows.png diff --git a/README b/README deleted file mode 100644 index 8931202d..00000000 --- a/README +++ /dev/null @@ -1,20 +0,0 @@ -This is the source distribution of SoundScape Renderer (SSR) licensed under the -GPLv3+. Please consult the file COPYING for more information about this license. - -The user manual in the doc/ directory contains relevant informations about the -SSR, including installation instructions. Additional (very detailed) -installation instructions can be found in the file INSTALL. - -For questions, bug reports and feature requests: - -Contact: ssr@spatialaudio.net -Website: http://spatialaudio.net/ssr/ -Documentation: https://ssr.readthedocs.io/ - -Copyright (c) 2016-2018 Division of Applied Acoustics - Chalmers University of Technology - -Copyright (c) 2012-2021 Institut für Nachrichtentechnik, Universität Rostock - -Copyright (c) 2006-2012 Quality & Usability Lab - Deutsche Telekom Laboratories, TU Berlin diff --git a/README.md b/README.md new file mode 100644 index 00000000..c813b876 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +[![Build Status](https://travis-ci.com/chris-hld/ssr.svg?branch=ssr-windows)](https://travis-ci.com/chris-hld/ssr) + +This is a fork of the SoundScape Renderer ([SSR](https://github.com/SoundScapeRenderer/ssr)), which aims at porting the source code to Windows. + +The basic idea is to cross-compile on a linux machine an executable (.exe) for Windows. +We use the M cross environment ([MXE](http://mxe.cc/)), which provides cross-compilation scripts for the dependencies and the MinGW64 (GCC) compiler. + +Pre-compiled binaries for Windows currently include: + `ssr-binaural.exe`, `ssr-brs.exe`, `ssr-vbap.exe`, `ssr-wfs.exe`, `ssr-aap.exe`, `ssr-dca.exe` and `ssr-generic.exe`. + +They should run on all x86-64 CPUs. +So far, only the Razor and Polhemus head-tracker are ported (and I can only test the recent Razor). + + +Getting started +--------------- +* Install Jack Audio for Windows (64bit) from [Jack Audio Downloads](http://www.jackaudio.org/downloads/). +* Get it running by following the [Installation and Configuration](http://jackaudio.org/faq/jack_on_windows.html). + Hint: If you plan on using other (ASIO) Audio-software with Jack Audio, don't forget to register the 64-bit JackRouter. +* Download and extract the latest [Release](https://github.com/chris-hld/ssr/releases). +It contains everything you need, including the cross-compiled executables. +* Adapt the configuration file `ssr.conf.windows` to your needs. Replace the paths (`Z:\SSR`) to yours. For now, please use absolute paths. + +Running the SSR on Windows +-------------------------- +* Have a look at the [Documentation](http://ssr.readthedocs.io/en/latest/operation.html#running-the-ssr) +* First, start the Jack Audio Server, e.g. with `qjackctl.exe`. +* Start the SSR. There is a simple example script `start-ssr.cmd`. +* Optional: Start your ASIO playback Software. +* Connect everything using Jack Audio Connection. + +This could look like this: + +![Jack](doc/manual/images/screenshot_jack.png) +![SSR-Windows](doc/manual/images/screenshot_ssr-windows.png) + + +--- + +This is the source distribution of SoundScape Renderer (SSR) licensed under the +GPLv3+. Please consult the file COPYING for more information about this license. + +The user manual in the doc/ directory contains relevant informations about the +SSR, including installation instructions. Additional (very detailed) +installation instructions can be found in the file INSTALL. + +For questions, bug reports and feature requests: + +Contact: ssr@spatialaudio.net +Website: http://spatialaudio.net/ssr/ +Documentation: http://ssr.readthedocs.io/en/latest/ + +Copyright (c) 2016-2018 Division of Applied Acoustics + Chalmers University of Technology + +Copyright (c) 2012-2014 Institut für Nachrichtentechnik, Universität Rostock + +Copyright (c) 2006-2012 Quality & Usability Lab +Deutsche Telekom Laboratories, TU Berlin + diff --git a/doc/manual/images/screenshot_jack.png b/doc/manual/images/screenshot_jack.png new file mode 100644 index 0000000000000000000000000000000000000000..9df011b7b2749d9d466534fa124892112f0d10cc GIT binary patch literal 22313 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 Lb4N>$T#5e=ZnO^8 literal 0 HcmV?d00001 From b99bf74f9039e07b3981be5f07749b1da7186958 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Fri, 2 Jun 2023 18:16:37 +0300 Subject: [PATCH 34/44] Update README --- README.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c813b876..d4bb235c 100644 --- a/README.md +++ b/README.md @@ -9,23 +9,20 @@ Pre-compiled binaries for Windows currently include: `ssr-binaural.exe`, `ssr-brs.exe`, `ssr-vbap.exe`, `ssr-wfs.exe`, `ssr-aap.exe`, `ssr-dca.exe` and `ssr-generic.exe`. They should run on all x86-64 CPUs. -So far, only the Razor and Polhemus head-tracker are ported (and I can only test the recent Razor). Getting started --------------- * Install Jack Audio for Windows (64bit) from [Jack Audio Downloads](http://www.jackaudio.org/downloads/). * Get it running by following the [Installation and Configuration](http://jackaudio.org/faq/jack_on_windows.html). - Hint: If you plan on using other (ASIO) Audio-software with Jack Audio, don't forget to register the 64-bit JackRouter. -* Download and extract the latest [Release](https://github.com/chris-hld/ssr/releases). -It contains everything you need, including the cross-compiled executables. -* Adapt the configuration file `ssr.conf.windows` to your needs. Replace the paths (`Z:\SSR`) to yours. For now, please use absolute paths. +* Download and run the latest installer [Release](https://github.com/chris-hld/ssr/releases). +* Adapt the configuration file e.g. `ssr.conf.windows` to your needs. Running the SSR on Windows -------------------------- * Have a look at the [Documentation](http://ssr.readthedocs.io/en/latest/operation.html#running-the-ssr) * First, start the Jack Audio Server, e.g. with `qjackctl.exe`. -* Start the SSR. There is a simple example script `start-ssr.cmd`. +* Start the SSR. Navigate a terminal to your installation folder and start from the terminal. * Optional: Start your ASIO playback Software. * Connect everything using Jack Audio Connection. @@ -39,7 +36,7 @@ This could look like this: This is the source distribution of SoundScape Renderer (SSR) licensed under the GPLv3+. Please consult the file COPYING for more information about this license. - + The user manual in the doc/ directory contains relevant informations about the SSR, including installation instructions. Additional (very detailed) installation instructions can be found in the file INSTALL. @@ -48,13 +45,13 @@ For questions, bug reports and feature requests: Contact: ssr@spatialaudio.net Website: http://spatialaudio.net/ssr/ -Documentation: http://ssr.readthedocs.io/en/latest/ +Documentation: https://ssr.readthedocs.io/ Copyright (c) 2016-2018 Division of Applied Acoustics Chalmers University of Technology - -Copyright (c) 2012-2014 Institut für Nachrichtentechnik, Universität Rostock + +Copyright (c) 2012-2021 Institut für Nachrichtentechnik, Universität Rostock Copyright (c) 2006-2012 Quality & Usability Lab -Deutsche Telekom Laboratories, TU Berlin + Deutsche Telekom Laboratories, TU Berlin From 0b6c36f0a0aeea46af2b9ebb62ddbc5d5ef22375 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 5 Jun 2023 12:01:34 +0300 Subject: [PATCH 35/44] Remove extra VERBOSE3 --- src/binauralrenderer.h | 1 - src/configuration.cpp | 1 - src/ssr_main.h | 1 - 3 files changed, 3 deletions(-) diff --git a/src/binauralrenderer.h b/src/binauralrenderer.h index 25c5df0b..b7a7e257 100644 --- a/src/binauralrenderer.h +++ b/src/binauralrenderer.h @@ -134,7 +134,6 @@ BinauralRenderer::_load_hrtfs(const std::string& filename, size_t size) auto idx = filename.find_last_of("."); if (idx != std::string::npos) { - SSR_VERBOSE3("Loading HRTFS"); auto ext = filename.substr(idx + 1); std::transform(ext.begin(), ext.end(), ext.begin() , [](unsigned char c){ return std::tolower(c); }); diff --git a/src/configuration.cpp b/src/configuration.cpp index eaf1be0d..df3380e3 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -632,7 +632,6 @@ ssr::conf_struct ssr::configuration(int& argc, char* argv[]) SSR_VERBOSE2(entry.first << " = " << entry.second); } - SSR_VERBOSE3("Done with parsing conf."); return conf; } diff --git a/src/ssr_main.h b/src/ssr_main.h index f9f9c550..3c7f6b62 100644 --- a/src/ssr_main.h +++ b/src/ssr_main.h @@ -49,7 +49,6 @@ int main(int argc, char* argv[]) std::signal(SIGTERM, signal_handler); try { - SSR_VERBOSE3("STARTING SSR"); // NB: This is static to be cleaned up automatically when exit() is called. static ssr::Controller controller{argc, argv}; controller.run(); From 1ce6a827929ee8b6cd2e8e241bd13071383b4cb2 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Mon, 5 Jun 2023 13:18:42 +0300 Subject: [PATCH 36/44] Add README to make CI happy --- README | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 00000000..8931202d --- /dev/null +++ b/README @@ -0,0 +1,20 @@ +This is the source distribution of SoundScape Renderer (SSR) licensed under the +GPLv3+. Please consult the file COPYING for more information about this license. + +The user manual in the doc/ directory contains relevant informations about the +SSR, including installation instructions. Additional (very detailed) +installation instructions can be found in the file INSTALL. + +For questions, bug reports and feature requests: + +Contact: ssr@spatialaudio.net +Website: http://spatialaudio.net/ssr/ +Documentation: https://ssr.readthedocs.io/ + +Copyright (c) 2016-2018 Division of Applied Acoustics + Chalmers University of Technology + +Copyright (c) 2012-2021 Institut für Nachrichtentechnik, Universität Rostock + +Copyright (c) 2006-2012 Quality & Usability Lab + Deutsche Telekom Laboratories, TU Berlin From 5e8d9f3c864bfba0ed132201a0e8a37b22c6b678 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 16:09:02 +0300 Subject: [PATCH 37/44] Document MXE package list --- CMakeLists.txt | 3 +-- data/ssr.conf.example | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3df97d21..8f04d30a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,3 @@ -# run e.g.: mkdir -p _build && cd _build && cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make -j3 && cd .. # Specify the minimum version for CMake message(STATUS "CMAKE_VERSION: " ${CMAKE_VERSION}) cmake_minimum_required(VERSION 3.8) @@ -364,7 +363,7 @@ foreach(executable ${EXECUTABLES}) endif(GUI) endforeach(executable ${EXECUTABLES}) - +# Using MXE with LOCAL_PKG_LIST := cc cmake fftw libsndfile libxml2 qtbase jack pthreads # x86_64-w64-mingw32.shared.posix-cmake -S . -B _build/ -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON # x86_64-w64-mingw32.shared.posix-cmake --build ./_build -j4 # ../mxe/tools/copydlldeps.sh --indir ./ssr-win-bin --destdir ./ssr-win-bin/deps --recursivesrcdir ../mxe/usr/x86_64-w64-mingw32.shared/ --srcdir ./_build --copy --enforcedir ./_build/*.dll --enforcedir ../mxe/usr/x86_64-w64-mingw32.shared/qt5/plugins/platforms/ diff --git a/data/ssr.conf.example b/data/ssr.conf.example index 762cddcf..332bcd39 100644 --- a/data/ssr.conf.example +++ b/data/ssr.conf.example @@ -24,7 +24,7 @@ #AUTO_ROTATION = off # Default Scene file name -#SCENE_FILE_NAME = my_scene.asd +SCENE_FILE_NAME = reproduction_setups/circle.asd # GUI scene shortcuts #SCENE_MENU = scene_menu.conf From 010edb8d924e76fdaad4818115120a3431a06eac Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 17:44:24 +0300 Subject: [PATCH 38/44] Create ssr-win-mxe.yml --- .github/workflows/ssr-win-mxe.yml | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/ssr-win-mxe.yml diff --git a/.github/workflows/ssr-win-mxe.yml b/.github/workflows/ssr-win-mxe.yml new file mode 100644 index 00000000..ffcc02ff --- /dev/null +++ b/.github/workflows/ssr-win-mxe.yml @@ -0,0 +1,32 @@ +name: Build SSR with different compilers +on: [push, pull_request] +jobs: + build-win: + runs-on: ubuntu-20.04 + defaults: + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Add MXE repository + run: | + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 86B72ED9 && \ + sudo add-apt-repository 'deb [arch=amd64] https://mirror.mxe.cc/repos/apt bionic main' && \ + sudo apt update + - name: Install pre-build MXE + run: | + sudo apt install ${PKG_PREFIX}-cc \ + ${PKG_PREFIX}-cmake \ + ${PKG_PREFIX}-pthreads \ + ${PKG_PREFIX}-fftw \ + ${PKG_PREFIX}-libsndfile \ + ${PKG_PREFIX}-libxml2 \ + ${PKG_PREFIX}-qtbase \ + ${PKG_PREFIX}-jack + + - name: adapt PATH + run: export PATH=/usr/lib/mxe/usr/bin:$PATH + - name: CMAKE + run: x86_64-w64-mingw32.shared-cmake -S . -B _build/ -DCMAKE_BUILD_TYPE=RELEASE -DVRPN=OFF -DSOFA=OFF .. + - name: BUILD + run: x86_64-w64-mingw32.shared-cmake --build ./_build -j4 From 32dee67ef2c7615b4ef05a6649a45a5e80c15876 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 17:45:41 +0300 Subject: [PATCH 39/44] Rename CI name --- .github/workflows/ssr-win-mxe.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ssr-win-mxe.yml b/.github/workflows/ssr-win-mxe.yml index ffcc02ff..a0531110 100644 --- a/.github/workflows/ssr-win-mxe.yml +++ b/.github/workflows/ssr-win-mxe.yml @@ -1,4 +1,4 @@ -name: Build SSR with different compilers +name: Build SSR-win with MXE on: [push, pull_request] jobs: build-win: From b6f1e64c1a6c9d5993a04b66b9470fda3ec03419 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 17:47:52 +0300 Subject: [PATCH 40/44] CI: Fix empty line --- .github/workflows/ssr-win-mxe.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ssr-win-mxe.yml b/.github/workflows/ssr-win-mxe.yml index a0531110..511d6891 100644 --- a/.github/workflows/ssr-win-mxe.yml +++ b/.github/workflows/ssr-win-mxe.yml @@ -3,11 +3,10 @@ on: [push, pull_request] jobs: build-win: runs-on: ubuntu-20.04 - defaults: steps: - name: Checkout uses: actions/checkout@v3 - + - name: Add MXE repository run: | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 86B72ED9 && \ From 1c11db1c3083cab75ef6b82d156ffa7a58fc7bef Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 17:49:32 +0300 Subject: [PATCH 41/44] CI: Fix missing PKG_PREFIX --- .github/workflows/ssr-win-mxe.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ssr-win-mxe.yml b/.github/workflows/ssr-win-mxe.yml index 511d6891..52f2212f 100644 --- a/.github/workflows/ssr-win-mxe.yml +++ b/.github/workflows/ssr-win-mxe.yml @@ -14,6 +14,7 @@ jobs: sudo apt update - name: Install pre-build MXE run: | + export PKG_PREFIX=mxe-x86-64-w64-mingw32.shared && \ sudo apt install ${PKG_PREFIX}-cc \ ${PKG_PREFIX}-cmake \ ${PKG_PREFIX}-pthreads \ From 25b828e3cbb13ce08c7aa0a62adc928694cbe72b Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 17:57:14 +0300 Subject: [PATCH 42/44] Use focal repo --- .github/workflows/ssr-win-mxe.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ssr-win-mxe.yml b/.github/workflows/ssr-win-mxe.yml index 52f2212f..5df2a74b 100644 --- a/.github/workflows/ssr-win-mxe.yml +++ b/.github/workflows/ssr-win-mxe.yml @@ -10,7 +10,7 @@ jobs: - name: Add MXE repository run: | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 86B72ED9 && \ - sudo add-apt-repository 'deb [arch=amd64] https://mirror.mxe.cc/repos/apt bionic main' && \ + sudo add-apt-repository 'deb [arch=amd64] https://mirror.mxe.cc/repos/apt focal main' && \ sudo apt update - name: Install pre-build MXE run: | From 279eb109c99342a659a4b1f7a4e1c5e717000339 Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 18:44:42 +0300 Subject: [PATCH 43/44] CI Cmake seems to be available as cmake-conf --- .github/workflows/ssr-win-mxe.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ssr-win-mxe.yml b/.github/workflows/ssr-win-mxe.yml index 5df2a74b..415a5bfc 100644 --- a/.github/workflows/ssr-win-mxe.yml +++ b/.github/workflows/ssr-win-mxe.yml @@ -16,7 +16,7 @@ jobs: run: | export PKG_PREFIX=mxe-x86-64-w64-mingw32.shared && \ sudo apt install ${PKG_PREFIX}-cc \ - ${PKG_PREFIX}-cmake \ + ${PKG_PREFIX}-cmake-conf \ ${PKG_PREFIX}-pthreads \ ${PKG_PREFIX}-fftw \ ${PKG_PREFIX}-libsndfile \ From 019469fb6c6adff88275602367d301e0ae50d01a Mon Sep 17 00:00:00 2001 From: Chris Hold Date: Tue, 6 Jun 2023 19:02:08 +0300 Subject: [PATCH 44/44] CI give more insight on apt paths --- .github/workflows/ssr-win-mxe.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ssr-win-mxe.yml b/.github/workflows/ssr-win-mxe.yml index 415a5bfc..90f89f08 100644 --- a/.github/workflows/ssr-win-mxe.yml +++ b/.github/workflows/ssr-win-mxe.yml @@ -15,7 +15,7 @@ jobs: - name: Install pre-build MXE run: | export PKG_PREFIX=mxe-x86-64-w64-mingw32.shared && \ - sudo apt install ${PKG_PREFIX}-cc \ + sudo apt install -y ${PKG_PREFIX}-cc \ ${PKG_PREFIX}-cmake-conf \ ${PKG_PREFIX}-pthreads \ ${PKG_PREFIX}-fftw \ @@ -25,8 +25,8 @@ jobs: ${PKG_PREFIX}-jack - name: adapt PATH - run: export PATH=/usr/lib/mxe/usr/bin:$PATH + run: ls /usr/lib/mxe/usr/bin && export PATH=/usr/lib/mxe/usr/bin:$PATH - name: CMAKE - run: x86_64-w64-mingw32.shared-cmake -S . -B _build/ -DCMAKE_BUILD_TYPE=RELEASE -DVRPN=OFF -DSOFA=OFF .. + run: /usr/lib/mxe/usr/bin/x86_64-w64-mingw32.shared-cmake -S . -B _build/ -DCMAKE_BUILD_TYPE=RELEASE -DVRPN=OFF -DSOFA=OFF .. - name: BUILD - run: x86_64-w64-mingw32.shared-cmake --build ./_build -j4 + run: /usr/lib/mxe/usr/bin/x86_64-w64-mingw32.shared-cmake --build ./_build -j4