From 43a0718d0bde76834e0d6e6d06208fc17000f73a Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 26 Mar 2016 12:48:28 +0000 Subject: [PATCH] Adding OpenBSD's sndio support. Updating jackmsr's work, adding sndio cmake module. Updating 64 bits OS arch detection (amd64). --- CMakeLists.txt | 12 ++ cmake/modules/DetectMachine.cmake | 4 +- cmake/modules/FindSndio.cmake | 32 +++++ include/AudioSndio.h | 54 ++++++++ include/MidiSndio.h | 48 +++++++ src/CMakeLists.txt | 2 + src/core/CMakeLists.txt | 2 + src/core/Mixer.cpp | 14 ++ src/core/audio/AudioSndio.cpp | 207 ++++++++++++++++++++++++++++++ src/core/midi/MidiSndio.cpp | 101 +++++++++++++++ src/gui/SetupDialog.cpp | 12 ++ src/lmmsconfig.h.in | 1 + 12 files changed, 487 insertions(+), 2 deletions(-) create mode 100644 cmake/modules/FindSndio.cmake create mode 100644 include/AudioSndio.h create mode 100644 include/MidiSndio.h create mode 100644 src/core/audio/AudioSndio.cpp create mode 100644 src/core/midi/MidiSndio.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fc6f3c8957f..ba10686cc7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -390,6 +390,16 @@ IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) FIND_PACKAGE(Threads) ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) +IF(LMMS_BUILD_OPENBSD) + FIND_PACKAGE(Sndio) + IF(SNDIO_FOUND) + SET(LMMS_HAVE_SNDIO TRUE) + SET(STATUS_SNDIO "OK") + ELSE() + SET(STATUS_SNDIO "") + ENDIF(SNDIO_FOUND) +ENDIF(LMMS_BUILD_OPENBSD) + # check for WINE IF(WANT_VST) FIND_PACKAGE(Wine) @@ -550,6 +560,7 @@ MESSAGE( "* ALSA : ${STATUS_ALSA}\n" "* JACK : ${STATUS_JACK}\n" "* OSS : ${STATUS_OSS}\n" +"* Sndio : ${STATUS_SNDIO}\n" "* PortAudio : ${STATUS_PORTAUDIO}\n" "* libsoundio : ${STATUS_SOUNDIO}\n" "* PulseAudio : ${STATUS_PULSEAUDIO}\n" @@ -561,6 +572,7 @@ MESSAGE( "-------------------------\n" "* ALSA : ${STATUS_ALSA}\n" "* OSS : ${STATUS_OSS}\n" +"* Sndio : ${STATUS_SNDIO}\n" "* WinMM : ${STATUS_WINMM}\n" "* AppleMidi : ${STATUS_APPLEMIDI}\n" ) diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index b5fb573fd31..60c4a0953ce 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -3,7 +3,7 @@ IF(WIN32) ELSEIF(APPLE) SET(LMMS_BUILD_APPLE 1) ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") - SET(LMMS_BUILD_OPENBSD 1) + SET(LMMS_BUILD_OPENBSD 1) ELSEIF(HAIKU) SET(LMMS_BUILD_HAIKU 1) ELSE() @@ -27,7 +27,7 @@ ELSE(WIN32) EXEC_PROGRAM( ${CMAKE_C_COMPILER} ARGS "-dumpmachine ${CMAKE_C_FLAGS}" OUTPUT_VARIABLE Machine ) MESSAGE("Machine: ${Machine}") STRING(REGEX MATCH "i.86" IS_X86 "${Machine}") - STRING(REGEX MATCH "86_64" IS_X86_64 "${Machine}") + STRING(REGEX MATCH "86_64|amd64" IS_X86_64 "${Machine}") ENDIF(WIN32) IF(IS_X86) diff --git a/cmake/modules/FindSndio.cmake b/cmake/modules/FindSndio.cmake new file mode 100644 index 00000000000..bf5b24c39a6 --- /dev/null +++ b/cmake/modules/FindSndio.cmake @@ -0,0 +1,32 @@ +# sndio check, based on FindAlsa.cmake +# + +# Copyright (c) 2006, David Faure, +# Copyright (c) 2007, Matthias Kretz +# Copyright (c) 2009, Jacob Meuser +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +include(CheckIncludeFiles) +include(CheckIncludeFileCXX) +include(CheckLibraryExists) + +# Already done by toplevel +find_library(SNDIO_LIBRARY sndio) +set(SNDIO_LIBRARY_DIR "") +if(SNDIO_LIBRARY) + get_filename_component(SNDIO_LIBRARY_DIR ${SNDIO_LIBRARY} PATH) +endif(SNDIO_LIBRARY) + +check_library_exists(sndio sio_open "${SNDIO_LIBRARY_DIR}" HAVE_SNDIO) +if(HAVE_SNDIO) + message(STATUS "Found sndio: ${SNDIO_LIBRARY}") +else(HAVE_SNDIO) + message(STATUS "sndio not found") +endif(HAVE_SNDIO) +set(SNDIO_FOUND ${HAVE_SNDIO}) + +find_path(SNDIO_INCLUDES sndio.h) + +mark_as_advanced(SNDIO_INCLUDES SNDIO_LIBRARY) diff --git a/include/AudioSndio.h b/include/AudioSndio.h new file mode 100644 index 00000000000..ce42883ad69 --- /dev/null +++ b/include/AudioSndio.h @@ -0,0 +1,54 @@ +#ifndef _AUDIO_SNDIO_H +#define _AUDIO_SNDIO_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_SNDIO + +#include + +#include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" + +class LcdSpinBox; +class QLineEdit; + + +class AudioSndio : public AudioDevice, public QThread +{ +public: + AudioSndio( bool & _success_ful, Mixer * _mixer ); + virtual ~AudioSndio(); + + inline static QString name( void ) + { + return QT_TRANSLATE_NOOP( "setupWidget", "sndio" ); + } + + class setupWidget : public AudioDeviceSetupWidget + { + public: + setupWidget( QWidget * _parent ); + virtual ~setupWidget(); + + virtual void saveSettings( void ); + + private: + QLineEdit * m_device; + LcdSpinBox * m_channels; + } ; + +private: + virtual void startProcessing( void ); + virtual void stopProcessing( void ); + virtual void applyQualitySettings( void ); + virtual void run( void ); + + struct sio_hdl *m_hdl; + struct sio_par m_par; +} ; + + +#endif /* LMMS_HAVE_SNDIO */ + +#endif /* _AUDIO_SNDIO_H */ diff --git a/include/MidiSndio.h b/include/MidiSndio.h new file mode 100644 index 00000000000..2b62938a6c7 --- /dev/null +++ b/include/MidiSndio.h @@ -0,0 +1,48 @@ +#ifndef _MIDI_SNDIO_H +#define _MIDI_SNDIO_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_SNDIO + +#include +#include + +#include + +#include "MidiClient.h" + +class QLineEdit; + + +class MidiSndio : public MidiClientRaw, public QThread +{ +public: + MidiSndio( void ); + virtual ~MidiSndio(); + + static QString probeDevice(void); + + inline static QString name(void) + { + return QT_TRANSLATE_NOOP("MidiSetupWidget", "sndio MIDI"); + } + + inline static QString configSection() + { + return "MidiSndio"; + } + + +protected: + virtual void sendByte(const unsigned char c); + virtual void run(void); + +private: + struct mio_hdl *m_hdl; + volatile bool m_quit; +} ; + +#endif /* LMMS_HAVE_SNDIO */ + +#endif /* _MIDI_SNDIO_H */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0a1388de33a..24cedbfd048 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,7 @@ INCLUDE_DIRECTORIES( ${JACK_INCLUDE_DIRS} ${SAMPLERATE_INCLUDE_DIRS} ${SNDFILE_INCLUDE_DIRS} + ${SNDIO_INCLUDE_DIRS} ) IF(NOT ("${SDL_INCLUDE_DIR}" STREQUAL "")) @@ -117,6 +118,7 @@ SET(LMMS_REQUIRED_LIBS ${SDL_LIBRARY} ${PORTAUDIO_LIBRARIES} ${SOUNDIO_LIBRARY} + ${SNDIO_LIBRARY} ${PULSEAUDIO_LIBRARIES} ${JACK_LIBRARIES} ${OGGVORBIS_LIBRARIES} diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5634940f787..eeda5122c43 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -71,6 +71,7 @@ set(LMMS_SRCS core/audio/AudioFileWave.cpp core/audio/AudioJack.cpp core/audio/AudioOss.cpp + core/audio/AudioSndio.cpp core/audio/AudioPort.cpp core/audio/AudioPortAudio.cpp core/audio/AudioSoundIo.cpp @@ -83,6 +84,7 @@ set(LMMS_SRCS core/midi/MidiClient.cpp core/midi/MidiController.cpp core/midi/MidiOss.cpp + core/midi/MidiSndio.cpp core/midi/MidiApple.cpp core/midi/MidiPort.cpp core/midi/MidiTime.cpp diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 6d3e0847476..f198f3b059b 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -40,6 +40,7 @@ #include "AudioAlsa.h" #include "AudioJack.h" #include "AudioOss.h" +#include "AudioSndio.h" #include "AudioPortAudio.h" #include "AudioSoundIo.h" #include "AudioPulseAudio.h" @@ -795,6 +796,19 @@ AudioDevice * Mixer::tryAudioDevices() } #endif +#ifdef LMMS_HAVE_SNDIO + if( dev_name == AudioSndio::name() || dev_name == "" ) + { + dev = new AudioSndio( success_ful, this ); + if( success_ful ) + { + m_audioDevName = AudioSndio::name(); + return dev; + } + delete dev; + } +#endif + #ifdef LMMS_HAVE_JACK if( dev_name == AudioJack::name() || dev_name == "" ) diff --git a/src/core/audio/AudioSndio.cpp b/src/core/audio/AudioSndio.cpp new file mode 100644 index 00000000000..301fe1e0cb0 --- /dev/null +++ b/src/core/audio/AudioSndio.cpp @@ -0,0 +1,207 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* license */ + +#include "AudioSndio.h" + +#ifdef LMMS_HAVE_SNDIO + +#include +#include +#include + +#include "endian_handling.h" +#include "LcdSpinBox.h" +#include "Engine.h" +#include "gui_templates.h" +#include "templates.h" + +#ifdef LMMS_HAVE_UNISTD_H +#include +#endif +#ifdef LMMS_HAVE_STDLIB_H +#include +#endif + +#include "ConfigManager.h" + + + +AudioSndio::AudioSndio(bool & _success_ful, Mixer * _mixer) : + AudioDevice( tLimit( + ConfigManager::inst()->value( "audiosndio", "channels" ).toInt(), + DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer ) +{ + _success_ful = FALSE; + + QString dev = ConfigManager::inst()->value( "audiosndio", "device" ); + + if (dev == "") + { + m_hdl = sio_open( NULL, SIO_PLAY, 0 ); + } + else + { + m_hdl = sio_open( dev.toAscii().data(), SIO_PLAY, 0 ); + } + + if( m_hdl == NULL ) + { + printf( "sndio: failed opening audio-device\n" ); + return; + } + + sio_initpar(&m_par); + + m_par.pchan = channels(); + m_par.bits = 16; + m_par.le = SIO_LE_NATIVE; + m_par.rate = sampleRate(); + m_par.round = mixer()->framesPerPeriod(); + m_par.appbufsz = m_par.round * 2; + + struct sio_par reqpar = m_par; + + if (!sio_setpar(m_hdl, &m_par)) + { + printf( "sndio: sio_setpar failed\n" ); + return; + } + if (!sio_getpar(m_hdl, &m_par)) + { + printf( "sndio: sio_getpar failed\n" ); + return; + } + + if (reqpar.pchan != m_par.pchan || + reqpar.bits != m_par.bits || + reqpar.le != m_par.le || + (abs(reqpar.rate - m_par.rate) * 100)/reqpar.rate > 2) + { + printf( "sndio: returned params not as requested\n" ); + return; + } + + if (!sio_start(m_hdl)) + { + printf( "sndio: sio_start failed\n" ); + return; + } + + _success_ful = TRUE; +} + + +AudioSndio::~AudioSndio() +{ + stopProcessing(); + if (m_hdl != NULL) + { + sio_close( m_hdl ); + m_hdl = NULL; + } +} + + +void AudioSndio::startProcessing( void ) +{ + if( !isRunning() ) + { + start( QThread::HighPriority ); + } +} + + +void AudioSndio::stopProcessing( void ) +{ + if( isRunning() ) + { + wait( 1000 ); + terminate(); + } +} + + +void AudioSndio::applyQualitySettings( void ) +{ + if( hqAudio() ) + { + setSampleRate( Engine::mixer()->processingSampleRate() ); + + /* change sample rate to sampleRate() */ + } + + AudioDevice::applyQualitySettings(); +} + + +void AudioSndio::run( void ) +{ + surroundSampleFrame * temp = + new surroundSampleFrame[mixer()->framesPerPeriod()]; + int_sample_t * outbuf = + new int_sample_t[mixer()->framesPerPeriod() * channels()]; + + while( TRUE ) + { + const fpp_t frames = getNextBuffer( temp ); + if( !frames ) + { + break; + } + + uint bytes = convertToS16( temp, frames, + mixer()->masterGain(), outbuf, FALSE ); + if( sio_write( m_hdl, outbuf, bytes ) != bytes ) + { + break; + } + } + + delete[] temp; + delete[] outbuf; +} + + +AudioSndio::setupWidget::setupWidget( QWidget * _parent ) : + AudioDeviceSetupWidget( AudioSndio::name(), _parent ) +{ + m_device = new QLineEdit( "", this ); + m_device->setGeometry( 10, 20, 160, 20 ); + + QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); + dev_lbl->setGeometry( 10, 40, 160, 10 ); + + LcdSpinBoxModel * m = new LcdSpinBoxModel( /* this */ ); + m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); + m->setStep( 2 ); + m->setValue( ConfigManager::inst()->value( "audiosndio", + "channels" ).toInt() ); + + m_channels = new LcdSpinBox( 1, this ); + m_channels->setModel( m ); + m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->move( 180, 20 ); + +} + + +AudioSndio::setupWidget::~setupWidget() +{ + +} + + +void AudioSndio::setupWidget::saveSettings( void ) +{ + ConfigManager::inst()->setValue( "audiosndio", "device", + m_device->text() ); + ConfigManager::inst()->setValue( "audiosndio", "channels", + QString::number( m_channels->value() ) ); +} + + +#endif /* LMMS_HAVE_SNDIO */ + +#endif /* SINGLE_SOURCE_COMPILE */ diff --git a/src/core/midi/MidiSndio.cpp b/src/core/midi/MidiSndio.cpp new file mode 100644 index 00000000000..e997a851bc3 --- /dev/null +++ b/src/core/midi/MidiSndio.cpp @@ -0,0 +1,101 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* license */ + +#include "MidiSndio.h" + +#ifdef LMMS_HAVE_SNDIO + +#include +#include + +#ifdef LMMS_HAVE_STDLIB_H +#include +#endif + +#include + +#include "ConfigManager.h" +#include "gui_templates.h" + + +MidiSndio::MidiSndio( void ) : + MidiClientRaw(), + m_quit( FALSE ) +{ + QString dev = probeDevice(); + + if (dev == "") + { + m_hdl = mio_open( NULL, MIO_IN | MIO_OUT, 0 ); + } + else + { + m_hdl = mio_open( dev.toAscii().data(), MIO_IN | MIO_OUT, 0 ); + } + + if( m_hdl == NULL ) + { + printf( "sndio: failed opening sndio midi device\n" ); + return; + } + + start( QThread::LowPriority ); +} + + +MidiSndio::~MidiSndio() +{ + if( isRunning() ) + { + m_quit = TRUE; + wait( 1000 ); + terminate(); + } +} + + +QString MidiSndio::probeDevice( void ) +{ + QString dev = ConfigManager::inst()->value( "MidiSndio", "device" ); + + return dev ; +} + + +void MidiSndio::sendByte( const unsigned char c ) +{ + mio_write( m_hdl, &c, 1 ); +} + + +void MidiSndio::run( void ) +{ + struct pollfd pfd; + nfds_t nfds; + char buf[0x100], *p; + size_t n; + int ret; + while( m_quit == FALSE && m_hdl ) + { + nfds = mio_pollfd( m_hdl, &pfd, POLLIN ); + ret = poll( &pfd, nfds, 100 ); + if ( ret < 0 ) + break; + if ( !ret || !( mio_revents( m_hdl, &pfd ) & POLLIN ) ) + continue; + n = mio_read( m_hdl, buf, sizeof(buf) ); + if ( !n ) + { + break; + } + for (p = buf; n > 0; n--, p++) + { + parseData( *p ); + } + } +} + +#endif /* LMMS_HAVE_SNDIO */ + +#endif /* SINGLE_SOURCE_COMPILE */ diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index ce1fb89c476..1f64f3c55fc 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -55,6 +55,7 @@ #include "AudioAlsaSetupWidget.h" #include "AudioJack.h" #include "AudioOss.h" +#include "AudioSndio.h" #include "AudioPortAudio.h" #include "AudioSoundIo.h" #include "AudioPulseAudio.h" @@ -65,6 +66,7 @@ #include "MidiAlsaRaw.h" #include "MidiAlsaSeq.h" #include "MidiOss.h" +#include "MidiSndio.h" #include "MidiWinMM.h" #include "MidiApple.h" #include "MidiDummy.h" @@ -801,6 +803,11 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : m_audioIfaceSetupWidgets[AudioOss::name()] = new AudioOss::setupWidget( asw ); #endif + +#ifdef LMMS_HAVE_SNDIO + m_audioIfaceSetupWidgets[AudioSndio::name()] = + new AudioSndio::setupWidget( asw ); +#endif m_audioIfaceSetupWidgets[AudioDummy::name()] = new AudioDummy::setupWidget( asw ); @@ -885,6 +892,11 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : MidiSetupWidget::create( msw ); #endif +#ifdef LMMS_HAVE_SNDIO + m_midiIfaceSetupWidgets[MidiSndio::name()] = + MidiSetupWidget::create( msw ); +#endif + #ifdef LMMS_BUILD_WIN32 m_midiIfaceSetupWidgets[MidiWinMM::name()] = MidiSetupWidget::create( msw ); diff --git a/src/lmmsconfig.h.in b/src/lmmsconfig.h.in index 9fcdfc176cb..0948d8529e8 100644 --- a/src/lmmsconfig.h.in +++ b/src/lmmsconfig.h.in @@ -13,6 +13,7 @@ #cmakedefine LMMS_HAVE_JACK #cmakedefine LMMS_HAVE_OGGVORBIS #cmakedefine LMMS_HAVE_OSS +#cmakedefine LMMS_HAVE_SNDIO #cmakedefine LMMS_HAVE_PORTAUDIO #cmakedefine LMMS_HAVE_SOUNDIO #cmakedefine LMMS_HAVE_PULSEAUDIO