Compare commits
258 Commits
v3.5.13-sr
...
master
@ -0,0 +1,6 @@
|
||||
[submodule "admin"]
|
||||
path = admin
|
||||
url = https://system@scm.trinitydesktop.org/scm/git/tde-common-admin
|
||||
[submodule "libltdl"]
|
||||
path = libltdl
|
||||
url = https://system@scm.trinitydesktop.org/scm/git/libltdl
|
@ -0,0 +1,190 @@
|
||||
#################################################
|
||||
#
|
||||
# (C) 2010 Serghei Amelian
|
||||
# serghei (DOT) amelian (AT) gmail.com
|
||||
#
|
||||
# Improvements and feedback are welcome
|
||||
#
|
||||
# This file is released under GPL >= 2
|
||||
#
|
||||
#################################################
|
||||
|
||||
|
||||
# required stuff
|
||||
|
||||
tde_setup_architecture_flags( )
|
||||
|
||||
include(TestBigEndian)
|
||||
test_big_endian(WORDS_BIGENDIAN)
|
||||
|
||||
tde_setup_largefiles( )
|
||||
|
||||
|
||||
##### check for TQt #############################
|
||||
|
||||
find_package( TQt )
|
||||
|
||||
|
||||
##### check for gcc visibility support #########
|
||||
|
||||
if( WITH_GCC_VISIBILITY )
|
||||
tde_setup_gcc_visibility( )
|
||||
endif( )
|
||||
|
||||
|
||||
##### check for include files ###################
|
||||
|
||||
check_include_file( "sys/time.h" HAVE_SYS_TIME_H )
|
||||
check_include_file( "time.h" TIME_WITH_SYS_TIME )
|
||||
check_include_file( "stdio.h" HAVE_STDIO_H )
|
||||
check_include_file( "stdlib.h" HAVE_STDLIB_H )
|
||||
check_include_file( "string.h" HAVE_STRING_H )
|
||||
check_include_file( "strings.h" HAVE_STRINGS_H )
|
||||
check_include_file( "ctype.h" HAVE_CTYPE_H )
|
||||
check_include_file( "malloc.h" HAVE_MALLOC_H )
|
||||
check_include_file( "memory.h" HAVE_MEMORY_H )
|
||||
check_include_file( "dlfcn.h" HAVE_DLFCN_H )
|
||||
check_include_file( "sys/soundcard.h" HAVE_SYS_SOUNDCARD_H )
|
||||
check_include_file( "pthread.h" HAVE_LIBPTHREAD )
|
||||
|
||||
|
||||
##### check for system libraries ################
|
||||
|
||||
set( DL_LIBRARIES dl )
|
||||
check_library_exists( ${DL_LIBRARIES} dlopen /lib HAVE_LIBDL )
|
||||
if( NOT HAVE_LIBDL )
|
||||
unset( DL_LIBRARIES )
|
||||
check_function_exists( dlopen HAVE_DLOPEN )
|
||||
if( HAVE_DLOPEN )
|
||||
set( HAVE_LIBDL 1 )
|
||||
endif( HAVE_DLOPEN )
|
||||
endif( NOT HAVE_LIBDL )
|
||||
|
||||
find_package( Threads )
|
||||
|
||||
|
||||
##### check for functions #######################
|
||||
|
||||
tde_save_and_set( CMAKE_REQUIRED_LIBRARIES ${DL_LIBRARIES} )
|
||||
check_function_exists( dlerror HAVE_DLERROR )
|
||||
check_function_exists( strcmp HAVE_STRCMP )
|
||||
check_function_exists( strchr HAVE_STRCHR )
|
||||
check_function_exists( index HAVE_INDEX )
|
||||
check_function_exists( strrchr HAVE_STRRCHR )
|
||||
check_function_exists( rindex HAVE_RINDEX )
|
||||
check_function_exists( memcpy HAVE_MEMCPY )
|
||||
check_function_exists( bcopy HAVE_BCOPY )
|
||||
tde_restore( CMAKE_REQUIRED_LIBRARIES )
|
||||
|
||||
check_prototype_definition( ioctl "int ioctl(int d, int request, ...)" "-1" "unistd.h;sys/ioctl.h" HAVE_IOCTL_INT_INT_DOTS )
|
||||
check_prototype_definition( ioctl "int ioctl(int d, unsigned long request, ...)" "-1" "unistd.h;sys/ioctl.h" HAVE_IOCTL_INT_ULONG_DOTS )
|
||||
|
||||
|
||||
##### check for audiofile #######################
|
||||
|
||||
set( HAVE_LIBAUDIOFILE 0 )
|
||||
if( WITH_AUDIOFILE )
|
||||
|
||||
pkg_search_module( AUDIOFILE audiofile )
|
||||
if( AUDIOFILE_FOUND )
|
||||
set( HAVE_LIBAUDIOFILE 1 )
|
||||
list( APPEND PC_LIB_REQUIRE "audiofile" )
|
||||
else( AUDIOFILE_FOUND )
|
||||
tde_message_fatal( "audiofile (wav) support is requested, but `libaudiofile` not found" )
|
||||
endif( AUDIOFILE_FOUND )
|
||||
|
||||
endif( WITH_AUDIOFILE )
|
||||
|
||||
|
||||
##### check for alsa ############################
|
||||
|
||||
set( HAVE_LIBASOUND2 0 )
|
||||
if( WITH_ALSA )
|
||||
|
||||
pkg_search_module( ALSA alsa )
|
||||
|
||||
if( ALSA_FOUND )
|
||||
|
||||
set( HAVE_LIBASOUND2 1 )
|
||||
|
||||
check_include_file( "alsa/asoundlib.h" HAVE_ALSA_ASOUNDLIB_H )
|
||||
if( NOT HAVE_ALSA_ASOUNDLIB_H )
|
||||
check_include_file( "sys/asoundlib.h" HAVE_SYS_ASOUNDLIB_H )
|
||||
endif( NOT HAVE_ALSA_ASOUNDLIB_H )
|
||||
|
||||
tde_save_and_set( CMAKE_REQUIRED_LIBRARIES ${ALSA_LIBRARIES} )
|
||||
check_function_exists( snd_pcm_resume HAVE_SND_PCM_RESUME )
|
||||
tde_restore( CMAKE_REQUIRED_LIBRARIES )
|
||||
|
||||
list( APPEND PC_LIB_REQUIRE "alsa" )
|
||||
|
||||
else( ALSA_FOUND )
|
||||
|
||||
tde_message_fatal( "ALSA support is requested, but not found on your system" )
|
||||
|
||||
endif( ALSA_FOUND )
|
||||
|
||||
endif( WITH_ALSA )
|
||||
|
||||
|
||||
##### check for esound #######################
|
||||
|
||||
set( HAVE_LIBESD 0 )
|
||||
if( WITH_ESOUND )
|
||||
|
||||
pkg_search_module( ESOUND esound )
|
||||
if( ESOUND_FOUND )
|
||||
set( HAVE_LIBESD 1 )
|
||||
list( APPEND PC_LIB_REQUIRE "esound" )
|
||||
else( ESOUND_FOUND )
|
||||
tde_message_fatal( "ESOUND support is requested, but `libesd` not found" )
|
||||
endif( ESOUND_FOUND )
|
||||
|
||||
endif( WITH_ESOUND )
|
||||
|
||||
|
||||
##### check for JACK ############################
|
||||
|
||||
set( HAVE_LIBJACK 0 )
|
||||
if( WITH_JACK )
|
||||
pkg_search_module( LIBJACK jack )
|
||||
if( LIBJACK_FOUND )
|
||||
set( HAVE_LIBJACK 1 )
|
||||
list( APPEND PC_LIB_REQUIRE "jack" )
|
||||
else( LIBJACK_FOUND )
|
||||
tde_message_fatal( "JACK support is requested, but `jack.pc` was not found" )
|
||||
endif( LIBJACK_FOUND )
|
||||
endif( WITH_JACK )
|
||||
|
||||
|
||||
##### check for SNDIO ###########################
|
||||
|
||||
set( HAVE_LIBSNDIO 0 )
|
||||
if( WITH_SNDIO )
|
||||
check_include_file( "sndio.h" HAVE_SNDIO_H )
|
||||
if( HAVE_SNDIO_H )
|
||||
set( HAVE_LIBSNDIO 1 )
|
||||
set( LIBSNDIO_LIBRARIES "sndio" )
|
||||
else( HAVE_SNDIO_H )
|
||||
tde_message_fatal( "SNDIO support is requested, but `sndio.h` was not found" )
|
||||
endif( HAVE_SNDIO_H )
|
||||
endif( WITH_SNDIO )
|
||||
|
||||
|
||||
##### check for glib/gthread modules ############
|
||||
|
||||
pkg_search_module( GLIB2 glib-2.0 )
|
||||
|
||||
if( GLIB2_FOUND )
|
||||
pkg_search_module( GTHREAD2 gthread-2.0 )
|
||||
if( NOT GTHREAD2_FOUND )
|
||||
tde_message_message( "gthread-2.0 is required, but not found on your system" )
|
||||
endif( NOT GTHREAD2_FOUND )
|
||||
else( GLIB2_FOUND )
|
||||
tde_message_fatal( "glib-2.0 is required, but not found on your system" )
|
||||
endif( GLIB2_FOUND )
|
||||
|
||||
|
||||
##### save cached value of required packages ####
|
||||
|
||||
set( PC_LIB_REQUIRE "${PC_LIB_REQUIRE}" CACHE INTERNAL "List of required packages" FORCE )
|
@ -0,0 +1,25 @@
|
||||
|
||||
aRts sound system
|
||||
|
||||
aRts is a short form for "analog realtime synthesizer". aRts is highly
|
||||
modular, creating and processing sound using small modules performing
|
||||
specific tasks. These may create a waveform (oscillators), play samples,
|
||||
filter data, add signals, perform effects like delay/flanger/chorus, or
|
||||
output the data to the soundcard.
|
||||
|
||||
All of the aRts documentation is now in "The aRts Handbook" which is
|
||||
in TDE DocBook format, part of tdemultimedia. It should be found on a
|
||||
KDE system in $TDEDIR/share/doc/tde/HTML/default/artsbuilder/index.html.
|
||||
|
||||
.
|
||||
|
||||
Contributing
|
||||
--------------
|
||||
|
||||
If you wish to contribute to aRts, you might do so:
|
||||
|
||||
- TDE Gitea Workspace (TGW) collaboration tool.
|
||||
https://mirror.git.trinitydesktop.org/gitea
|
||||
|
||||
- TDE Weblate Translation Workspace (TWTW) collaboration tool.
|
||||
https://mirror.git.trinitydesktop.org/weblate
|
@ -0,0 +1 @@
|
||||
Subproject commit 59a8bf7c09f87fbccd6dc2987145c7216e043e77
|
@ -1,11 +0,0 @@
|
||||
Begin4
|
||||
Title: arts
|
||||
Version: 1.5.10
|
||||
Entered-date: 2008-08-26
|
||||
Description: Soundserver for the K Desktop Environment (KDE)
|
||||
Keywords: KDE X11 desktop Qt
|
||||
Author: http://bugs.kde.org/ (KDE Bugtracking System)
|
||||
Primary-site: http://www.kde.org/download/
|
||||
Platforms: Unix, Qt
|
||||
Copying-policy: LGPL, Artistic
|
||||
End
|
@ -0,0 +1,11 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
arts_version=@ARTS_VERSION@
|
||||
|
||||
Name: aRtsC
|
||||
Description: aRts sound system C support library (TDE)
|
||||
Version: 0.9.5
|
||||
Libs: -L${libdir} -lartsc @LIBDL@ @USE_THREADS@ @LIBPTHREAD@ @GLIB_LDFLAGS@ @GLIB_LIBADD@
|
||||
Cflags: -I${includedir} @GLIB_CFLAGS@
|
@ -1,5 +0,0 @@
|
||||
All of the aRts documentation is now in "The aRts Handbook" which is
|
||||
in KDE DocBook format, part of kdemultimedia. It should be found on a
|
||||
KDE system in $KDEDIR/share/doc/HTML/default/artsbuilder/index.html.
|
||||
|
||||
An on-line version can be found at http://www.arts-project.org/doc/handbook
|
@ -0,0 +1,41 @@
|
||||
.TH "ARTSC-CONFIG" "1"
|
||||
.SH "NAME"
|
||||
artsc-config \(em Get information about a libartsc installation
|
||||
.SH "SYNOPSIS"
|
||||
.PP
|
||||
\fBartsc-config\fR [\fB\-\-arts-prefix\fI\fR\fP] [\fB\-\-arts-version\fI\fR\fP] [\fB\-\-cflags\fI\fR\fP] [\fB\-\-libs\fI\fR\fP] [\fB\-\-version\fI\fR\fP]
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
This manual page documents briefly the
|
||||
\fBartsc-config\fR command.
|
||||
.PP
|
||||
\fBartsc-config\fR displays information about a previous libartsc installation.
|
||||
.SH "OPTIONS"
|
||||
.PP
|
||||
This program follows the usual GNU command line syntax,
|
||||
with long options starting with two dashes (`\-'). A summary of
|
||||
options is included below.
|
||||
.IP "\fB\-\-arts-prefix\fP " 10
|
||||
This is the prefix used when libartsc was installed.
|
||||
.IP "\fB\-\-arts-version\fP " 10
|
||||
Outputs version information about the installed arts.
|
||||
.IP "\fB\-\-cflags\fP " 10
|
||||
Set of compiler options (CFLAGS) to use when compiling files that use libartsc.
|
||||
.IP "\fB\-\-libs\fP " 10
|
||||
Shows the complete set of libs and other linker options you will need in order to link your application with libartsc.
|
||||
.IP "\fB\-\-version\fP " 10
|
||||
Outputs version information about the installed libartsc.
|
||||
.SH "AUTHOR"
|
||||
.PP
|
||||
This manual page was written by Chris Cheney
|
||||
<ccheney@debian.org> for the \fBDebian\fP system (but may be used by
|
||||
others). Permission is granted to copy, distribute and/or
|
||||
modify this document under the terms of the GNU General Public
|
||||
License, Version 2 or any later version published by the Free
|
||||
Software Foundation.
|
||||
|
||||
.PP
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in /usr/share/common-licenses/GPL.
|
||||
|
||||
.\" created by instant / docbook-to-man
|
@ -0,0 +1,43 @@
|
||||
.TH "ARTSCAT" "1"
|
||||
.SH "NAME"
|
||||
artscat \(em pipe data to sound device
|
||||
.SH "SYNOPSIS"
|
||||
.PP
|
||||
\fBartscat\fR [\fB\fI options \fR\fP] [\fB\fI filename \fR\fP]
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
This manual page documents briefly the
|
||||
\fBartscat\fR command.
|
||||
.PP
|
||||
\fBartscat\fR pipes data from a pipe to the sound device through arts.
|
||||
.SH "OPTIONS"
|
||||
.PP
|
||||
This program follows the usual GNU command line syntax,
|
||||
with long options starting with two dashes (`\-'). A summary of
|
||||
options is included below.
|
||||
.IP "\fB-b \fIbits\fR\fP " 10
|
||||
set number of bits (8 or 16)
|
||||
.IP "\fB-c \fIchannels\fR\fP " 10
|
||||
set number of channels (1 or 2)
|
||||
.IP "\fB-h\fP " 10
|
||||
display help and exit
|
||||
.IP "\fB-r \fIsamplingrate\fR\fP " 10
|
||||
set samplingrate to use
|
||||
.IP "\fB-t \fItitle\fR\fP " 10
|
||||
set stream title
|
||||
.IP "\fB-v\fP " 10
|
||||
show version
|
||||
.SH "AUTHOR"
|
||||
.PP
|
||||
This manual page was written by Chris Cheney
|
||||
<ccheney@debian.org> for the \fBDebian\fP system (but may be used by
|
||||
others). Permission is granted to copy, distribute and/or
|
||||
modify this document under the terms of the GNU General Public
|
||||
License, Version 2 or any later version published by the Free
|
||||
Software Foundation.
|
||||
|
||||
.PP
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in /usr/share/common-licenses/GPL.
|
||||
|
||||
.\" created by instant / docbook-to-man
|
@ -0,0 +1,31 @@
|
||||
.TH ARTSDSP "1" "February 2008" "artsdsp" "User Commands"
|
||||
.SH NAME
|
||||
artsdsp \- manual page for artsdsp
|
||||
.SH DESCRIPTION
|
||||
artsdsp \- attempt to reroute audio device to artsd
|
||||
.PP
|
||||
artsdsp [options] binary
|
||||
.PP
|
||||
options:
|
||||
.TP
|
||||
.B \-h, \-\-help
|
||||
Show brief help.
|
||||
.TP
|
||||
.B \-n, \-\-name\fR=\fINAME\fR
|
||||
Use name to identify player to artsd.
|
||||
.TP
|
||||
.B \-m, \-\-mmap
|
||||
Emulate memory mapping (i.e. for quake).
|
||||
.TP
|
||||
.B \-s, \-\-single\-threaded
|
||||
Use the single\-threaded version.
|
||||
.TP
|
||||
.B \-v, \-\-verbose
|
||||
Show parameters.
|
||||
.TP
|
||||
.B \-V, \-\-version
|
||||
Show version.
|
||||
.PP
|
||||
This manual page was written by Fathi Boudra <fabo@debian.org>,
|
||||
for the Debian project (but may be used by others).
|
||||
|
@ -1,561 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (C) 2000,2001 Jozef Kosoru
|
||||
jozef.kosoru@pobox.sk
|
||||
(C) 2000,2001 Stefan Westerfeld
|
||||
stefan@space.twc.de
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* only compile 'alsa' AudioIO class if configure thinks it is a good idea
|
||||
*/
|
||||
#ifdef HAVE_LIBASOUND
|
||||
|
||||
#ifdef HAVE_ALSA_ASOUNDLIB_H
|
||||
#include <alsa/asoundlib.h>
|
||||
#elif defined(HAVE_SYS_ASOUNDLIB_H)
|
||||
#include <sys/asoundlib.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h> // Needed on some systems.
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "debug.h"
|
||||
#include "audioio.h"
|
||||
|
||||
namespace Arts {
|
||||
|
||||
class AudioIOALSA : public AudioIO {
|
||||
protected:
|
||||
int audio_read_fd;
|
||||
int audio_write_fd;
|
||||
int requestedFragmentSize;
|
||||
int requestedFragmentCount;
|
||||
|
||||
enum BufferMode{block, stream};
|
||||
int m_card;
|
||||
int m_device;
|
||||
int m_format;
|
||||
BufferMode m_bufferMode;
|
||||
|
||||
snd_pcm_t *m_pcm_handle;
|
||||
snd_pcm_channel_info_t m_cinfo;
|
||||
snd_pcm_format_t m_cformat;
|
||||
snd_pcm_channel_params_t m_params;
|
||||
snd_pcm_channel_setup_t m_setup;
|
||||
|
||||
int setPcmParams(const int channel);
|
||||
void checkCapabilities();
|
||||
|
||||
public:
|
||||
AudioIOALSA();
|
||||
|
||||
void setParam(AudioParam param, int& value);
|
||||
int getParam(AudioParam param);
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
int read(void *buffer, int size);
|
||||
int write(void *buffer, int size);
|
||||
};
|
||||
|
||||
REGISTER_AUDIO_IO(AudioIOALSA,"alsa","Advanced Linux Sound Architecture");
|
||||
};
|
||||
|
||||
using namespace std;
|
||||
using namespace Arts;
|
||||
|
||||
AudioIOALSA::AudioIOALSA()
|
||||
{
|
||||
param(samplingRate) = 44100;
|
||||
paramStr(deviceName) = "/dev/dsp"; //!! alsa doesn't need this
|
||||
requestedFragmentSize = param(fragmentSize) = 1024;
|
||||
requestedFragmentCount = param(fragmentCount) = 7;
|
||||
param(channels) = 2;
|
||||
param(direction) = directionWrite;
|
||||
|
||||
/*
|
||||
* default parameters
|
||||
*/
|
||||
m_card = snd_defaults_pcm_card(); //!! need interface !!
|
||||
m_device = snd_defaults_pcm_device(); //!!
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
m_format = SND_PCM_SFMT_S16_BE;
|
||||
#else
|
||||
m_format = SND_PCM_SFMT_S16_LE;
|
||||
#endif
|
||||
m_bufferMode = block; //block/stream (stream mode doesn't work yet)
|
||||
|
||||
if(m_card >= 0) {
|
||||
char* cardname = 0;
|
||||
|
||||
if(snd_card_get_name(m_card, &cardname) == 0 && cardname != 0)
|
||||
{
|
||||
//!! thats not what devicename is intended to do
|
||||
//!! devicename is an input information into
|
||||
//!! the "driver", to select which card to use
|
||||
//!! not an output information
|
||||
paramStr(deviceName) = cardname;
|
||||
free(cardname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioIOALSA::open()
|
||||
{
|
||||
string& _error = paramStr(lastError);
|
||||
string& _deviceName = paramStr(deviceName);
|
||||
int& _channels = param(channels);
|
||||
int& _fragmentSize = param(fragmentSize);
|
||||
int& _fragmentCount = param(fragmentCount);
|
||||
int& _samplingRate = param(samplingRate);
|
||||
int& _direction = param(direction);
|
||||
int& _format = param(format);
|
||||
|
||||
/*
|
||||
* initialize format - TODO: implement fallback (i.e. if no format given,
|
||||
* it should try 16bit first, then fall back to 8bit)
|
||||
*/
|
||||
switch(_format)
|
||||
{
|
||||
default: _format = 16;
|
||||
|
||||
case 16: // 16bit, signed little endian
|
||||
m_format = SND_PCM_SFMT_S16_LE;
|
||||
break;
|
||||
|
||||
case 17: // 16bit, signed big endian
|
||||
m_format = SND_PCM_SFMT_S16_BE;
|
||||
break;
|
||||
|
||||
case 8: // 8bit, unsigned
|
||||
m_format = SND_PCM_SFMT_U8;
|
||||
break;
|
||||
}
|
||||
|
||||
/* open pcm device */
|
||||
int mode = SND_PCM_OPEN_NONBLOCK;
|
||||
|
||||
if(_direction == directionReadWrite)
|
||||
mode |= SND_PCM_OPEN_DUPLEX;
|
||||
else if(_direction == directionWrite)
|
||||
mode |= SND_PCM_OPEN_PLAYBACK;
|
||||
else
|
||||
{
|
||||
_error = "invalid direction";
|
||||
return false;
|
||||
}
|
||||
|
||||
int err;
|
||||
if((err = snd_pcm_open(&m_pcm_handle, m_card, m_device, mode)) < 0) {
|
||||
_error = "device: ";
|
||||
_error += _deviceName.c_str();
|
||||
_error += " can't be opened (";
|
||||
_error += snd_strerror(err);
|
||||
_error += ")";
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
artsdebug("ALSA driver: %s", _deviceName.c_str());
|
||||
}
|
||||
|
||||
snd_pcm_nonblock_mode(m_pcm_handle, 0);
|
||||
|
||||
/* flush buffers */
|
||||
(void)snd_pcm_capture_flush(m_pcm_handle);
|
||||
if(_direction & directionRead)
|
||||
(void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE);
|
||||
if(_direction & directionWrite)
|
||||
(void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
|
||||
|
||||
/* check device capabilities */
|
||||
checkCapabilities();
|
||||
|
||||
/* set the fragment settings to what the user requested */
|
||||
_fragmentSize = requestedFragmentSize;
|
||||
_fragmentCount = requestedFragmentCount;
|
||||
|
||||
/* set PCM communication parameters */
|
||||
if((_direction & directionRead) && setPcmParams(SND_PCM_CHANNEL_CAPTURE))
|
||||
return false;
|
||||
if((_direction & directionWrite) && setPcmParams(SND_PCM_CHANNEL_PLAYBACK))
|
||||
return false;
|
||||
|
||||
/* prepare channel */
|
||||
if((_direction & directionRead) &&
|
||||
snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE) < 0)
|
||||
{
|
||||
_error = "Unable to prepare capture channel!";
|
||||
return false;
|
||||
}
|
||||
if((_direction & directionWrite) &&
|
||||
snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
|
||||
{
|
||||
_error = "Unable to prepare playback channel!";
|
||||
return false;
|
||||
}
|
||||
|
||||
/* obtain current PCM setup (may differ from requested one) */
|
||||
(void)memset(&m_setup, 0, sizeof(m_setup));
|
||||
|
||||
m_setup.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
if(snd_pcm_channel_setup(m_pcm_handle, &m_setup) < 0) {
|
||||
_error = "Unable to obtain channel setup!";
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check samplerate */
|
||||
const int tolerance = _samplingRate/10+1000;
|
||||
if(abs(m_setup.format.rate-_samplingRate) > tolerance)
|
||||
{
|
||||
_error = "Can't set requested sampling rate!";
|
||||
char details[80];
|
||||
sprintf(details," (requested rate %d, got rate %d)",
|
||||
_samplingRate, m_setup.format.rate);
|
||||
_error += details;
|
||||
return false;
|
||||
}
|
||||
_samplingRate = m_setup.format.rate;
|
||||
|
||||
/* check format */
|
||||
if(m_setup.format.format != m_format) {
|
||||
_error = "Can't set requested format:";
|
||||
_error += snd_pcm_get_format_name(m_format);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check voices */
|
||||
if(m_setup.format.voices != _channels) {
|
||||
_error = "Audio device doesn't support number of requested channels!";
|
||||
return false;
|
||||
}
|
||||
|
||||
/* update fragment settings with what we got */
|
||||
switch(m_bufferMode) {
|
||||
case block:
|
||||
_fragmentSize = m_setup.buf.block.frag_size;
|
||||
_fragmentCount = m_setup.buf.block.frags_max-1;
|
||||
break;
|
||||
case stream:
|
||||
_fragmentSize = m_setup.buf.stream.queue_size;
|
||||
_fragmentCount = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
artsdebug("buffering: %d fragments with %d bytes "
|
||||
"(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
|
||||
(float)(_fragmentSize*_fragmentCount) /
|
||||
(float)(2.0 * _samplingRate * _channels)*1000.0);
|
||||
|
||||
/* obtain PCM file descriptor(s) */
|
||||
audio_read_fd = audio_write_fd = -1;
|
||||
|
||||
if(_direction & directionRead)
|
||||
audio_read_fd = snd_pcm_file_descriptor(m_pcm_handle,
|
||||
SND_PCM_CHANNEL_CAPTURE);
|
||||
if(_direction & directionWrite)
|
||||
audio_write_fd = snd_pcm_file_descriptor(m_pcm_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK);
|
||||
|
||||
/* start recording */
|
||||
if((_direction & directionRead) && snd_pcm_capture_go(m_pcm_handle)) {
|
||||
_error = "Can't start recording!";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioIOALSA::close()
|
||||
{
|
||||
int& _direction = param(direction);
|
||||
if(_direction & directionRead)
|
||||
(void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE);
|
||||
if(_direction & directionWrite)
|
||||
(void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
|
||||
(void)snd_pcm_close(m_pcm_handle);
|
||||
}
|
||||
|
||||
void AudioIOALSA::setParam(AudioParam p, int& value)
|
||||
{
|
||||
switch(p)
|
||||
{
|
||||
case fragmentSize:
|
||||
param(p) = requestedFragmentSize = value;
|
||||
break;
|
||||
case fragmentCount:
|
||||
param(p) = requestedFragmentCount = value;
|
||||
break;
|
||||
default:
|
||||
param(p) = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int AudioIOALSA::getParam(AudioParam p)
|
||||
{
|
||||
snd_pcm_channel_status_t status;
|
||||
(void)memset(&status, 0, sizeof(status));
|
||||
|
||||
switch(p)
|
||||
{
|
||||
case canRead:
|
||||
status.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||
if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
|
||||
arts_warning("Capture channel status error!");
|
||||
return -1;
|
||||
}
|
||||
return status.free;
|
||||
break;
|
||||
|
||||
case canWrite:
|
||||
status.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
|
||||
arts_warning("Playback channel status error!");
|
||||
return -1;
|
||||
}
|
||||
return status.free;
|
||||
break;
|
||||
|
||||
case selectReadFD:
|
||||
return audio_read_fd;
|
||||
break;
|
||||
|
||||
case selectWriteFD:
|
||||
return audio_write_fd;
|
||||
break;
|
||||
|
||||
case autoDetect:
|
||||
/*
|
||||
* that the ALSA driver could be compiled doesn't say anything
|
||||
* about whether it will work (the user might be using an OSS
|
||||
* kernel driver) so we'll use a value less than the OSS one
|
||||
* here, because OSS will most certainly work (ALSA's OSS emu)
|
||||
*/
|
||||
return 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
return param(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int AudioIOALSA::read(void *buffer, int size)
|
||||
{
|
||||
int length;
|
||||
do {
|
||||
length = snd_pcm_read(m_pcm_handle, buffer, size);
|
||||
} while (length == -EINTR);
|
||||
if(length == -EPIPE) {
|
||||
snd_pcm_channel_status_t status;
|
||||
(void)memset(&status, 0, sizeof(status));
|
||||
status.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||
if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
|
||||
arts_info("Capture channel status error!");
|
||||
return -1;
|
||||
}
|
||||
else if(status.status == SND_PCM_STATUS_RUNNING) {
|
||||
length = 0;
|
||||
}
|
||||
else if(status.status == SND_PCM_STATUS_OVERRUN) {
|
||||
artsdebug("Overrun at position: %d" ,status.scount);
|
||||
if(snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE)<0)
|
||||
{
|
||||
arts_info("Overrun: capture prepare error!");
|
||||
return -1;
|
||||
}
|
||||
length = 0;
|
||||
}
|
||||
else {
|
||||
arts_info("Unknown capture error!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(length < 0) {
|
||||
arts_info("Capture error: %s", snd_strerror(length));
|
||||
return -1;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
int AudioIOALSA::write(void *buffer, int size)
|
||||
{
|
||||
int length;
|
||||
while((length = snd_pcm_write(m_pcm_handle, buffer, size)) != size) {
|
||||
if (length == -EINTR)
|
||||
continue; // Try again
|
||||
snd_pcm_channel_status_t status;
|
||||
(void)memset(&status, 0, sizeof(status));
|
||||
status.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
|
||||
if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
|
||||
arts_warning("Playback channel status error!");
|
||||
return -1;
|
||||
}
|
||||
else if(status.status == SND_PCM_STATUS_UNDERRUN) {
|
||||
artsdebug("Underrun at position: %d", status.scount);
|
||||
if(snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK)
|
||||
< 0) {
|
||||
arts_warning("Underrun: playback prepare error!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
arts_warning("Unknown playback error!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int AudioIOALSA::setPcmParams(const int channel)
|
||||
{
|
||||
int &_samplingRate = param(samplingRate);
|
||||
int &_channels = param(channels);
|
||||
int &_fragmentSize = param(fragmentSize);
|
||||
int &_fragmentCount = param(fragmentCount);
|
||||
|
||||
(void)memset(&m_cformat, 0, sizeof(m_cformat));
|
||||
m_cformat.interleave = 1;
|
||||
m_cformat.format = m_format;
|
||||
m_cformat.rate = _samplingRate;
|
||||
m_cformat.voices = _channels;
|
||||
|
||||
(void)memset(&m_params, 0, sizeof(m_params));
|
||||
switch(m_bufferMode){
|
||||
case stream:
|
||||
m_params.mode=SND_PCM_MODE_STREAM;
|
||||
break;
|
||||
case block:
|
||||
m_params.mode=SND_PCM_MODE_BLOCK;
|
||||
break;
|
||||
}
|
||||
m_params.channel=channel;
|
||||
(void)memcpy(&m_params.format, &m_cformat, sizeof(m_cformat));
|
||||
if(channel==SND_PCM_CHANNEL_CAPTURE){
|
||||
m_params.start_mode=SND_PCM_START_GO;
|
||||
m_params.stop_mode=SND_PCM_STOP_ROLLOVER;
|
||||
}
|
||||
else{ //SND_PCM_CHANNEL_PLAYBACK
|
||||
m_params.start_mode= (m_bufferMode==block) ? SND_PCM_START_FULL : SND_PCM_START_DATA;
|
||||
m_params.stop_mode=SND_PCM_STOP_ROLLOVER; // SND_PCM_STOP_STOP
|
||||
//use this ^^^ if you want to track underruns
|
||||
}
|
||||
|
||||
switch(m_bufferMode){
|
||||
case stream:
|
||||
m_params.buf.stream.queue_size=1024*1024; //_fragmentSize*_fragmentCount;
|
||||
m_params.buf.stream.fill=SND_PCM_FILL_SILENCE_WHOLE;
|
||||
m_params.buf.stream.max_fill=1024;
|
||||
break;
|
||||
case block:
|
||||
m_params.buf.block.frag_size=_fragmentSize;
|
||||
if(channel==SND_PCM_CHANNEL_CAPTURE){
|
||||
m_params.buf.block.frags_max=1;
|
||||
m_params.buf.block.frags_min=1;
|
||||
}
|
||||
else{ //SND_PCM_CHANNEL_PLAYBACK
|
||||
m_params.buf.block.frags_max=_fragmentCount+1;
|
||||
m_params.buf.block.frags_min=1;
|
||||
}
|
||||
}
|
||||
if(snd_pcm_channel_params(m_pcm_handle, &m_params)<0){
|
||||
paramStr(lastError) = "Unable to set channel params!";
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioIOALSA::checkCapabilities()
|
||||
{
|
||||
snd_pcm_info_t info;
|
||||
(void)memset(&info, 0, sizeof(info));
|
||||
if(!snd_pcm_info(m_pcm_handle, &info)) {
|
||||
string flags = "";
|
||||
if(info.flags & SND_PCM_INFO_PLAYBACK) flags += "playback ";
|
||||
if(info.flags & SND_PCM_INFO_CAPTURE) flags += "capture ";
|
||||
if(info.flags & SND_PCM_INFO_DUPLEX) flags += "duplex ";
|
||||
if(info.flags & SND_PCM_INFO_DUPLEX_RATE) flags += "duplex_rate ";
|
||||
artsdebug(" type:%d id:%s\n"
|
||||
" flags:%s\n"
|
||||
" playback_subdevices:%d capture_subdevices:%d",
|
||||
info.type, info.id,
|
||||
flags.c_str(),
|
||||
info.playback+1, info.capture+1);
|
||||
}
|
||||
else {
|
||||
arts_warning("Can't get device info!"); //not fatal error
|
||||
}
|
||||
|
||||
(void)memset(&m_cinfo, 0, sizeof(m_cinfo));
|
||||
m_cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
if(!snd_pcm_channel_info(m_pcm_handle, &m_cinfo)) {
|
||||
string flags = "";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_MMAP) flags += "mmap ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_STREAM) flags += "stream ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_BLOCK) flags += "block ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_BATCH) flags += "batch ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_INTERLEAVE) flags += "interleave ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_NONINTERLEAVE) flags += "noninterleave ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_BLOCK_TRANSFER) flags += "block_transfer ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_OVERRANGE) flags += "overrange ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_MMAP_VALID) flags += "mmap_valid ";
|
||||
if(m_cinfo.flags & SND_PCM_CHNINFO_PAUSE) flags += "pause ";
|
||||
|
||||
artsdebug(" subdevice:%d\n"
|
||||
" flags:%s\n"
|
||||
" min_rate:%d max_rate:%d\n"
|
||||
" buffer_size:%d min_fragment_size:%d max_fragment_size:%d\n"
|
||||
" fragment_align:%d fifo_size:%d transfer_block_size:%d\n"
|
||||
" mmap_size:%d",
|
||||
m_cinfo.subdevice,
|
||||
flags.c_str(),
|
||||
m_cinfo.min_rate, m_cinfo.max_rate,
|
||||
m_cinfo.buffer_size, m_cinfo.min_fragment_size, m_cinfo.max_fragment_size,
|
||||
m_cinfo.fragment_align, m_cinfo.fifo_size, m_cinfo.transfer_block_size,
|
||||
m_cinfo.mmap_size);
|
||||
}
|
||||
else {
|
||||
arts_warning("Can't get channel info!"); //not fatal error
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBASOUND */
|
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Jacob Meuser <jakemsr@sdf.lonestar.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBSNDIO
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <sndio.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "audioio.h"
|
||||
#include "audiosubsys.h"
|
||||
#include "iomanager.h"
|
||||
#include "dispatcher.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
int bps, chans;
|
||||
long long realpos, playpos, recpos;
|
||||
|
||||
void movecb(void *addr, int delta)
|
||||
{
|
||||
realpos += delta * (int)(bps * chans);
|
||||
}
|
||||
|
||||
namespace Arts {
|
||||
|
||||
class AudioIOSNDIO : public AudioIO, public TimeNotify {
|
||||
|
||||
protected:
|
||||
struct sio_hdl *hdl;
|
||||
struct sio_par par;
|
||||
int bufsz;
|
||||
int bufused;
|
||||
int duplex;
|
||||
|
||||
public:
|
||||
AudioIOSNDIO();
|
||||
|
||||
void notifyTime();
|
||||
|
||||
void setParam(AudioParam param, int& value);
|
||||
int getParam(AudioParam param);
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
int read(void *buffer, int size);
|
||||
int write(void *buffer, int size);
|
||||
};
|
||||
|
||||
REGISTER_AUDIO_IO(AudioIOSNDIO,"sndio","libsndio");
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
using namespace Arts;
|
||||
|
||||
AudioIOSNDIO::AudioIOSNDIO()
|
||||
{
|
||||
/* default parameters */
|
||||
param(samplingRate) = 48000;
|
||||
paramStr(deviceName) = "";
|
||||
param(fragmentSize) = 4096;
|
||||
param(fragmentCount) = 4;
|
||||
param(format) = 16;
|
||||
param(channels) = 2;
|
||||
param(direction) = directionWrite;
|
||||
}
|
||||
|
||||
bool AudioIOSNDIO::open()
|
||||
{
|
||||
string& _error = paramStr(lastError);
|
||||
string& _deviceName = paramStr(deviceName);
|
||||
int& _channels = param(channels);
|
||||
int& _fragmentSize = param(fragmentSize);
|
||||
int& _fragmentCount = param(fragmentCount);
|
||||
int& _samplingRate = param(samplingRate);
|
||||
int& _format = param(format);
|
||||
|
||||
struct sio_par testpar;
|
||||
char dev[PATH_MAX];
|
||||
int mode, bpf;
|
||||
|
||||
duplex = 0;
|
||||
if (param(direction) == (directionRead | directionWrite)) {
|
||||
mode = SIO_PLAY | SIO_REC;
|
||||
duplex = 1;
|
||||
} else if (param(direction) == directionWrite) {
|
||||
mode = SIO_PLAY;
|
||||
} else {
|
||||
_error = "invalid direction";
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy(dev, _deviceName.c_str(), PATH_MAX);
|
||||
|
||||
if (strcmp(dev, "") == 0)
|
||||
hdl = sio_open(NULL, mode, 0);
|
||||
else
|
||||
hdl = sio_open(dev, mode, 0);
|
||||
|
||||
if (hdl == NULL) {
|
||||
_error = "device ";
|
||||
if (strcmp(_deviceName.c_str(), "") == 0)
|
||||
_error += "(default sndio device)";
|
||||
else
|
||||
_error += _deviceName.c_str();
|
||||
_error += " can't be opened";
|
||||
return false;
|
||||
}
|
||||
|
||||
sio_initpar(&par);
|
||||
|
||||
if (_format == 8) {
|
||||
par.bits = 8;
|
||||
par.sig = 0;
|
||||
} else {
|
||||
par.bits = 16;
|
||||
par.sig = 1;
|
||||
par.le = 1;
|
||||
}
|
||||
|
||||
if (duplex)
|
||||
par.pchan = par.rchan = _channels;
|
||||
else
|
||||
par.pchan = _channels;
|
||||
|
||||
par.rate = _samplingRate;
|
||||
|
||||
/* limit the buffer size for hardware constraints */
|
||||
|
||||
if (_fragmentSize > 1024*16)
|
||||
_fragmentSize = 1024*16;
|
||||
|
||||
while (_fragmentSize * _fragmentCount > 1024*32)
|
||||
_fragmentCount--;
|
||||
|
||||
bpf = ((par.bits / NBBY) * par.pchan);
|
||||
par.round = _fragmentSize / bpf;
|
||||
par.appbufsz = _fragmentSize * _fragmentCount / bpf;
|
||||
|
||||
testpar = par;
|
||||
|
||||
char details[128];
|
||||
|
||||
snprintf(details, 128, " rate=%d pchan=%d bits=%d le=%d sig=%d sz=%d",
|
||||
par.rate, par.pchan, par.bits, par.le, par.sig, par.appbufsz);
|
||||
|
||||
if (!sio_setpar(hdl, &par)) {
|
||||
_error = "sio_setpar failed:";
|
||||
_error += details;
|
||||
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sio_getpar(hdl, &par)) {
|
||||
_error = "sio_getpar failed";
|
||||
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (testpar.bits != par.bits ||
|
||||
testpar.sig != par.sig ||
|
||||
testpar.le != par.le ||
|
||||
testpar.pchan != par.pchan ||
|
||||
fabs((testpar.rate - par.rate)/testpar.rate) > 0.05) {
|
||||
_error = "returned params do not match requested params";
|
||||
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
bpf = par.pchan * par.bps;
|
||||
bufsz = par.bufsz * bpf;
|
||||
|
||||
::bps = par.bps;
|
||||
::chans = par.pchan;
|
||||
::realpos = ::playpos = ::recpos = 0;
|
||||
|
||||
sio_onmove(hdl, ::movecb, NULL);
|
||||
|
||||
if (!sio_start(hdl)) {
|
||||
_error = "sio_start failed";
|
||||
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* use a timer instead of select() */
|
||||
Dispatcher::the()->ioManager()->addTimer(10, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioIOSNDIO::close()
|
||||
{
|
||||
if (hdl != NULL) {
|
||||
sio_close(hdl);
|
||||
hdl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioIOSNDIO::setParam(AudioParam p, int& value)
|
||||
{
|
||||
param(p) = value;
|
||||
}
|
||||
|
||||
int AudioIOSNDIO::getParam(AudioParam p)
|
||||
{
|
||||
struct pollfd gpfd;
|
||||
int n, events;
|
||||
|
||||
/* update ::realpos */
|
||||
if ((p == canRead || p == canWrite) && hdl != NULL) {
|
||||
events = POLLOUT;
|
||||
if (duplex)
|
||||
events |= POLLIN;
|
||||
n = sio_pollfd(hdl, &gpfd, events);
|
||||
while (poll(&gpfd, n, 0) < 0 && errno == EINTR)
|
||||
;
|
||||
sio_revents(hdl, &gpfd);
|
||||
}
|
||||
|
||||
switch(p) {
|
||||
case canRead:
|
||||
bufused = (::realpos - ::recpos < 0) ? 0 : ::realpos - ::recpos;
|
||||
return bufused;
|
||||
break;
|
||||
case canWrite:
|
||||
bufused = (::realpos < 0) ? ::playpos : ::playpos - ::realpos;
|
||||
return bufsz - bufused;
|
||||
break;
|
||||
case autoDetect:
|
||||
return 15;
|
||||
break;
|
||||
default:
|
||||
return param(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int AudioIOSNDIO::read(void *buffer, int size)
|
||||
{
|
||||
arts_assert(hdl != NULL);
|
||||
|
||||
size_t result;
|
||||
|
||||
result = sio_read(hdl, buffer, size);
|
||||
|
||||
::recpos += result;
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
int AudioIOSNDIO::write(void *buffer, int size)
|
||||
{
|
||||
arts_assert(hdl != NULL);
|
||||
|
||||
size_t result;
|
||||
|
||||
result = sio_write(hdl, buffer, size);
|
||||
|
||||
::playpos += result;
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
void AudioIOSNDIO::notifyTime()
|
||||
{
|
||||
int& _direction = param(direction);
|
||||
|
||||
for (;;) {
|
||||
int todo = 0;
|
||||
|
||||
if ((_direction & directionRead) && (getParam(canRead) > 0))
|
||||
todo |= AudioSubSystem::ioRead;
|
||||
|
||||
if ((_direction & directionWrite) && (getParam(canWrite) > 0))
|
||||
todo |= AudioSubSystem::ioWrite;
|
||||
|
||||
if (todo == 0)
|
||||
return;
|
||||
|
||||
AudioSubSystem::the()->handleIO(todo);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,112 @@
|
||||
#################################################
|
||||
#
|
||||
# (C) 2010 Serghei Amelian
|
||||
# serghei (DOT) amelian (AT) gmail.com
|
||||
#
|
||||
# Improvements and feedback are welcome
|
||||
#
|
||||
# This file is released under GPL >= 2
|
||||
#
|
||||
#################################################
|
||||
|
||||
include( CheckCSourceCompiles )
|
||||
include( CheckTypeSize )
|
||||
|
||||
|
||||
##### check for ogg/vorbis ######################
|
||||
|
||||
set( GSL_HAVE_OGGVORBIS 0 )
|
||||
if( WITH_VORBIS )
|
||||
|
||||
pkg_search_module( VORBIS vorbis )
|
||||
|
||||
if( VORBIS_FOUND )
|
||||
|
||||
pkg_search_module( VORBISFILE vorbisfile )
|
||||
|
||||
if( VORBISFILE_FOUND )
|
||||
|
||||
set( GSL_HAVE_OGGVORBIS 1 )
|
||||
|
||||
tde_save_and_set( CMAKE_REQUIRED_LIBRARIES ${VORBISFILE_LIBRARIES} )
|
||||
check_c_source_compiles(
|
||||
"#include <vorbis/vorbisfile.h>
|
||||
int main() { ov_read_float(0,0,0); return 0; } "
|
||||
GSL_HAVE_OGGVORBIS_RC3 )
|
||||
if( NOT GSL_HAVE_OGGVORBIS_RC3 )
|
||||
set( GSL_HAVE_OGGVORBIS_RC3 0 )
|
||||
endif( NOT GSL_HAVE_OGGVORBIS_RC3 )
|
||||
tde_restore( CMAKE_REQUIRED_LIBRARIES )
|
||||
|
||||
list( APPEND PC_LIB_REQUIRE "vorbis" "vorbisfile" )
|
||||
|
||||
else( VORBISFILE_FOUND )
|
||||
|
||||
tde_message_fatal( "Ogg/Vorbis support are requested, but `libvorbisfile` not found" )
|
||||
|
||||
endif( VORBISFILE_FOUND )
|
||||
|
||||
else( VORBIS_FOUND )
|
||||
|
||||
tde_message_fafal( "Ogg/Vorbis support are requested, but `libvorbis` but found" )
|
||||
|
||||
endif( VORBIS_FOUND )
|
||||
|
||||
endif( WITH_VORBIS )
|
||||
|
||||
|
||||
##### check for libmad MPEG decoder #############
|
||||
|
||||
set( GSL_HAVE_LIBMAD 0 )
|
||||
if( WITH_MAD )
|
||||
|
||||
pkg_search_module( MAD libmad )
|
||||
set( MAD_MODULE_NAME "libmad" )
|
||||
if( NOT MAD_FOUND )
|
||||
pkg_search_module( MAD mad )
|
||||
set( MAD_MODULE_NAME "mad" )
|
||||
endif()
|
||||
|
||||
if( MAD_FOUND )
|
||||
set( GSL_HAVE_LIBMAD 1 )
|
||||
list( APPEND PC_LIB_REQUIRE ${MAD_MODULE_NAME} )
|
||||
else( MAD_FOUND )
|
||||
find_library( MAD_LIBRARIES NAMES mad )
|
||||
find_path( MAD_INCLUDE_DIRS mad.h )
|
||||
if( NOT MAD_LIBRARIES )
|
||||
tde_message_fatal( "MAD support is requested, but `libmad` not found" )
|
||||
endif( NOT MAD_LIBRARIES )
|
||||
endif( MAD_FOUND )
|
||||
|
||||
endif( WITH_MAD )
|
||||
|
||||
|
||||
##### check for some type sizes #################
|
||||
|
||||
check_type_size( pthread_mutex_t GSL_SIZEOF_PTH_MUTEX_T )
|
||||
check_type_size( pthread_cond_t GSL_SIZEOF_PTH_COND_T )
|
||||
check_type_size( intmax_t GSL_SIZEOF_STD_INTMAX_T )
|
||||
|
||||
tde_save_and_set( CMAKE_REQUIRED_LIBRARIES ${CMAKE_THREAD_LIBS_INIT} )
|
||||
check_c_source_compiles(
|
||||
"#define _XOPEN_SOURCE 500
|
||||
#include <pthread.h>
|
||||
int main()
|
||||
{
|
||||
int (*attr_settype) (pthread_mutexattr_t *__attr, int __kind) = pthread_mutexattr_settype;
|
||||
int val = PTHREAD_MUTEX_RECURSIVE; attr_settype = 0; val = 0;
|
||||
return 0;
|
||||
}"
|
||||
GSL_HAVE_MUTEXATTR_SETTYPE )
|
||||
if( NOT GSL_HAVE_MUTEXATTR_SETTYPE )
|
||||
set( GSL_HAVE_MUTEXATTR_SETTYPE 0 )
|
||||
endif( NOT GSL_HAVE_MUTEXATTR_SETTYPE )
|
||||
tde_restore( CMAKE_REQUIRED_LIBRARIES )
|
||||
|
||||
set( GSL_USE_GSL_GLIB 1 )
|
||||
set( GSL_USE_ARTS_THREADS 1 )
|
||||
|
||||
|
||||
##### save cached value of required packages ####
|
||||
|
||||
set( PC_LIB_REQUIRE "${PC_LIB_REQUIRE}" CACHE INTERNAL "List of required packages" FORCE )
|
@ -0,0 +1 @@
|
||||
Subproject commit 754b445fd5519ddca551a45b9ae6385d3ee451bb
|
Loading…
Reference in new issue