aboutsummaryrefslogtreecommitdiff
path: root/pd/portaudio/pa_linux_alsa
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portaudio/pa_linux_alsa')
-rw-r--r--pd/portaudio/pa_linux_alsa/blocking_calls.c61
-rw-r--r--pd/portaudio/pa_linux_alsa/callback_thread.c374
-rw-r--r--pd/portaudio/pa_linux_alsa/pa_linux_alsa.c989
-rw-r--r--pd/portaudio/pa_linux_alsa/pa_linux_alsa.h45
4 files changed, 0 insertions, 1469 deletions
diff --git a/pd/portaudio/pa_linux_alsa/blocking_calls.c b/pd/portaudio/pa_linux_alsa/blocking_calls.c
deleted file mode 100644
index 6304b117..00000000
--- a/pd/portaudio/pa_linux_alsa/blocking_calls.c
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#include "pa_stream.h"
-
-#include "pa_linux_alsa.h"
-
-PaError ReadStream( PaStream* s,
- void *buffer,
- unsigned long frames )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- /* TODO: handle failure, xruns */
-
- if( stream->capture_interleaved )
- {
- snd_pcm_mmap_readi( stream->pcm_capture, buffer, frames );
- }
- else
- {
- snd_pcm_mmap_readn( stream->pcm_capture, (void**)buffer, frames );
- }
-
- return paNoError;
-}
-
-
-PaError WriteStream( PaStream* s,
- void *buffer,
- unsigned long frames )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- if( stream->playback_interleaved )
- {
- snd_pcm_mmap_writei( stream->pcm_playback, buffer, frames );
- }
- else
- {
- snd_pcm_mmap_writen( stream->pcm_playback, (void**)buffer, frames );
- }
-
- return paNoError;
-}
-
-
-unsigned long GetStreamReadAvailable( PaStream* s )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- return snd_pcm_avail_update( stream->pcm_capture );
-}
-
-
-unsigned long GetStreamWriteAvailable( PaStream* s )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- return snd_pcm_avail_update( stream->pcm_playback );
-}
-
-
diff --git a/pd/portaudio/pa_linux_alsa/callback_thread.c b/pd/portaudio/pa_linux_alsa/callback_thread.c
deleted file mode 100644
index 483557b6..00000000
--- a/pd/portaudio/pa_linux_alsa/callback_thread.c
+++ /dev/null
@@ -1,374 +0,0 @@
-
-#include <sys/poll.h>
-#include <limits.h>
-#include <math.h> /* abs() */
-
-#include <alsa/asoundlib.h>
-
-#include "pa_linux_alsa.h"
-
-#define MIN(x,y) ( (x) < (y) ? (x) : (y) )
-
-static int wait( PaAlsaStream *stream )
-{
- int need_capture;
- int need_playback;
- int capture_avail = INT_MAX;
- int playback_avail = INT_MAX;
- int common_avail;
-
- if( stream->pcm_capture )
- need_capture = 1;
- else
- need_capture = 0;
-
- if( stream->pcm_playback )
- need_playback = 1;
- else
- need_playback = 0;
-
- while( need_capture || need_playback )
- {
- int playback_pfd_offset=0;
- int total_fds = 0;
-
- /* if the main thread has requested that we stop, do so now */
- pthread_testcancel();
-
- /*printf("still polling...\n");
- if( need_capture )
- printf("need capture.\n");
- if( need_playback )
- printf("need playback.\n"); */
-
- /* get the fds, packing all applicable fds into a single array,
- * so we can check them all with a single poll() call */
-
- if( need_capture )
- {
- snd_pcm_poll_descriptors( stream->pcm_capture, stream->pfds,
- stream->capture_nfds );
- total_fds += stream->capture_nfds;
- }
-
- if( need_playback )
- {
- playback_pfd_offset = total_fds;
- snd_pcm_poll_descriptors( stream->pcm_playback,
- stream->pfds + playback_pfd_offset,
- stream->playback_nfds );
- total_fds += stream->playback_nfds;
- }
-
- /* now poll on the combination of playback and capture fds.
- * TODO: handle interrupt and/or failure */
- poll( stream->pfds, total_fds, 1000 );
-
- /* check the return status of our pfds */
- if( need_capture )
- {
- short revents;
- snd_pcm_poll_descriptors_revents( stream->pcm_capture, stream->pfds,
- stream->capture_nfds, &revents );
- if( revents == POLLIN )
- need_capture = 0;
- }
-
- if( need_playback )
- {
- short revents;
- snd_pcm_poll_descriptors_revents( stream->pcm_playback,
- stream->pfds + playback_pfd_offset,
- stream->playback_nfds, &revents );
- //if( revents & POLLOUT )
- //if( revents & POLLERR )
- // printf("polling error!");
- if( revents == POLLOUT )
- need_playback = 0;
- }
- }
-
- /* we have now established that there are buffers ready to be
- * operated on. Now determine how many frames are available. */
- if( stream->pcm_capture )
- capture_avail = snd_pcm_avail_update( stream->pcm_capture );
-
- if( stream->pcm_playback )
- playback_avail = snd_pcm_avail_update( stream->pcm_playback );
-
- common_avail = MIN(capture_avail, playback_avail);
- common_avail -= common_avail % stream->frames_per_period;
-
- return common_avail;
-}
-
-static int setup_buffers( PaAlsaStream *stream, int frames_avail )
-{
- int i;
- int capture_frames_avail = INT_MAX;
- int playback_frames_avail = INT_MAX;
- int common_frames_avail;
-
- if( stream->pcm_capture )
- {
- const snd_pcm_channel_area_t *capture_areas;
- const snd_pcm_channel_area_t *area;
- snd_pcm_uframes_t frames = frames_avail;
-
- /* I do not understand this code fragment yet, it is copied out of the
- * alsa-devel archives... */
- snd_pcm_mmap_begin( stream->pcm_capture, &capture_areas,
- &stream->capture_offset, &frames);
-
- if( stream->capture_interleaved )
- {
- void *interleaved_capture_buffer;
- area = &capture_areas[0];
- interleaved_capture_buffer = area->addr +
- (area->first + area->step * stream->capture_offset) / 8;
- PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
- 0, /* starting at channel 0 */
- interleaved_capture_buffer,
- 0 /* default numInputChannels */
- );
- }
- else
- {
- /* noninterleaved */
- void *noninterleaved_capture_buffers[1000];
- for( i = 0; i < stream->capture_channels; i++ )
- {
- area = &capture_areas[i];
- noninterleaved_capture_buffers[i] = area->addr +
- (area->first + area->step * stream->capture_offset) / 8;
- PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor,
- i,
- noninterleaved_capture_buffers[i]);
- }
- }
-
- capture_frames_avail = frames;
- }
-
- if( stream->pcm_playback )
- {
- const snd_pcm_channel_area_t *playback_areas;
- const snd_pcm_channel_area_t *area;
- snd_pcm_uframes_t frames = frames_avail;
-
- /* I do not understand this code fragment yet, it is copied out of the
- * alsa-devel archives... */
- snd_pcm_mmap_begin( stream->pcm_playback, &playback_areas,
- &stream->playback_offset, &frames);
-
- if( stream->playback_interleaved )
- {
- void *interleaved_playback_buffer;
- area = &playback_areas[0];
- interleaved_playback_buffer = area->addr +
- (area->first + area->step * stream->playback_offset) / 8;
- PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
- 0, /* starting at channel 0 */
- interleaved_playback_buffer,
- 0 /* default numInputChannels */
- );
- }
- else
- {
- /* noninterleaved */
- void *noninterleaved_playback_buffers[1000];
- for( i = 0; i < stream->playback_channels; i++ )
- {
- area = &playback_areas[i];
- noninterleaved_playback_buffers[i] = area->addr +
- (area->first + area->step * stream->playback_offset) / 8;
- PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor,
- i,
- noninterleaved_playback_buffers[i]);
- }
- }
-
- playback_frames_avail = frames;
- }
-
-
- common_frames_avail = MIN(capture_frames_avail, playback_frames_avail);
- common_frames_avail -= common_frames_avail % stream->frames_per_period;
- //printf( "%d capture frames available\n", capture_frames_avail );
- //printf( "%d frames playback available\n", playback_frames_avail );
- //printf( "%d frames available\n", common_frames_avail );
-
- if( stream->pcm_capture )
- PaUtil_SetInputFrameCount( &stream->bufferProcessor, common_frames_avail );
-
- if( stream->pcm_playback )
- PaUtil_SetOutputFrameCount( &stream->bufferProcessor, common_frames_avail );
-
- return common_frames_avail;
-}
-
-void *CallbackThread( void *userData )
-{
- PaAlsaStream *stream = (PaAlsaStream*)userData;
-
- if( stream->pcm_capture )
- snd_pcm_start( stream->pcm_capture );
- if( stream->pcm_playback )
- snd_pcm_start( stream->pcm_playback );
-
- while(1)
- {
- int frames_avail;
- int frames_got;
-
- PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
- int callbackResult;
- int framesProcessed;
-
- pthread_testcancel();
- {
- /* calculate time info */
- snd_timestamp_t capture_timestamp;
- snd_timestamp_t playback_timestamp;
- snd_pcm_status_t *capture_status;
- snd_pcm_status_t *playback_status;
- snd_pcm_status_alloca( &capture_status );
- snd_pcm_status_alloca( &playback_status );
-
- if( stream->pcm_capture )
- {
- snd_pcm_status( stream->pcm_capture, capture_status );
- snd_pcm_status_get_tstamp( capture_status, &capture_timestamp );
- }
- if( stream->pcm_playback )
- {
- snd_pcm_status( stream->pcm_playback, playback_status );
- snd_pcm_status_get_tstamp( playback_status, &playback_timestamp );
- }
-
- /* Hmm, we potentially have both a playback and a capture timestamp.
- * Hopefully they are the same... */
- if( stream->pcm_capture && stream->pcm_playback )
- {
- float capture_time = capture_timestamp.tv_sec +
- ((float)capture_timestamp.tv_usec/1000000);
- float playback_time= playback_timestamp.tv_sec +
- ((float)playback_timestamp.tv_usec/1000000);
- if( fabsf(capture_time-playback_time) > 0.01 )
- printf("Capture time and playback time differ by %f\n", fabsf(capture_time-playback_time));
- timeInfo.currentTime = capture_time;
- }
- else if( stream->pcm_playback )
- {
- timeInfo.currentTime = playback_timestamp.tv_sec +
- ((float)playback_timestamp.tv_usec/1000000);
- }
- else
- {
- timeInfo.currentTime = capture_timestamp.tv_sec +
- ((float)capture_timestamp.tv_usec/1000000);
- }
-
- if( stream->pcm_capture )
- {
- snd_pcm_sframes_t capture_delay = snd_pcm_status_get_delay( capture_status );
- timeInfo.inputBufferAdcTime = timeInfo.currentTime -
- (float)capture_delay / stream->streamRepresentation.streamInfo.sampleRate;
- }
-
- if( stream->pcm_playback )
- {
- snd_pcm_sframes_t playback_delay = snd_pcm_status_get_delay( playback_status );
- timeInfo.outputBufferDacTime = timeInfo.currentTime +
- (float)playback_delay / stream->streamRepresentation.streamInfo.sampleRate;
- }
- }
-
-
- /*
- IMPLEMENT ME:
- - handle buffer slips
- */
-
- /*
- depending on whether the host buffers are interleaved, non-interleaved
- or a mixture, you will want to call PaUtil_ProcessInterleavedBuffers(),
- PaUtil_ProcessNonInterleavedBuffers() or PaUtil_ProcessBuffers() here.
- */
-
- frames_avail = wait( stream );
- //printf( "%d frames available\n", frames_avail );
-
- /* Now we know the soundcard is ready to produce/receive at least
- * one period. We just need to get the buffers for the client
- * to read/write. */
- PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo );
-
- frames_got = setup_buffers( stream, frames_avail );
-
- if( frames_avail == frames_got )
- ;//printf("good, they were both %d\n", frames_avail );
- else
- printf("damn, they were different: avail: %d, got: %d\n", frames_avail, frames_got );
-
- /* this calls the callback */
-
- PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
-
- framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor,
- &callbackResult );
-
- PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
-
- /* inform ALSA how many frames we wrote */
-
- if( stream->pcm_capture )
- snd_pcm_mmap_commit( stream->pcm_capture, stream->capture_offset, frames_avail );
-
- if( stream->pcm_playback )
- snd_pcm_mmap_commit( stream->pcm_playback, stream->playback_offset, frames_avail );
-
-
- /*
- If you need to byte swap outputBuffer, you can do it here using
- routines in pa_byteswappers.h
- */
-
- if( callbackResult == paContinue )
- {
- /* nothing special to do */
- }
- else if( callbackResult == paAbort )
- {
- stream->callback_finished = 1;
-
- if( stream->pcm_capture )
- {
- snd_pcm_drop( stream->pcm_capture );
- }
-
- if( stream->pcm_playback )
- {
- snd_pcm_drop( stream->pcm_playback );
- }
- pthread_exit(NULL);
- }
- else
- {
- stream->callback_finished = 1;
-
- if( stream->pcm_capture )
- {
- snd_pcm_drain( stream->pcm_capture );
- }
-
- if( stream->pcm_playback )
- {
- snd_pcm_drain( stream->pcm_playback );
- }
- pthread_exit(NULL);
- }
-
- }
-}
-
diff --git a/pd/portaudio/pa_linux_alsa/pa_linux_alsa.c b/pd/portaudio/pa_linux_alsa/pa_linux_alsa.c
deleted file mode 100644
index 9582b5b8..00000000
--- a/pd/portaudio/pa_linux_alsa/pa_linux_alsa.c
+++ /dev/null
@@ -1,989 +0,0 @@
-/*
- * $Id: pa_linux_alsa.c,v 1.1.2.3 2003/02/01 21:55:03 joshua Exp $
- * PortAudio Portable Real-Time Audio Library
- * Latest Version at: http://www.portaudio.com
- * ALSA implementation by Joshua Haberman
- *
- * Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
- *
- * Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <sys/poll.h>
-#include <pthread.h>
-
-#include <string.h> /* strlen() */
-#include <limits.h>
-
-#include <alsa/asoundlib.h>
-
-#include "portaudio.h"
-#include "pa_util.h"
-#include "pa_allocation.h"
-#include "pa_hostapi.h"
-#include "pa_stream.h"
-#include "pa_cpuload.h"
-#include "pa_process.h"
-
-#include "pa_linux_alsa.h"
-
-/* PaAlsaHostApiRepresentation - host api datastructure specific to this implementation */
-
-typedef struct
-{
- PaUtilHostApiRepresentation commonHostApiRep;
- PaUtilStreamInterface callbackStreamInterface;
- PaUtilStreamInterface blockingStreamInterface;
-
- PaUtilAllocationGroup *allocations;
-
- PaHostApiIndex hostApiIndex;
-}
-PaAlsaHostApiRepresentation;
-
-
-/* prototypes for functions declared in this file */
-
-PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex );
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
- PaStream** s,
- const PaStreamParameters *inputParameters,
- const PaStreamParameters *outputParameters,
- double sampleRate,
- unsigned long framesPerBuffer,
- PaStreamFlags streamFlags,
- PaStreamCallback *callback,
- void *userData );
-static PaError CloseStream( PaStream* stream );
-static PaError StartStream( PaStream *stream );
-static PaError StopStream( PaStream *stream );
-static PaError AbortStream( PaStream *stream );
-static PaError IsStreamStopped( PaStream *s );
-static PaError IsStreamActive( PaStream *stream );
-static PaTime GetStreamTime( PaStream *stream );
-static double GetStreamCpuLoad( PaStream* stream );
-static PaError BuildDeviceList( PaAlsaHostApiRepresentation *hostApi );
-
-/* blocking calls are in blocking_calls.c */
-extern PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
-extern PaError WriteStream( PaStream* stream, void *buffer, unsigned long frames );
-extern signed long GetStreamReadAvailable( PaStream* stream );
-extern signed long GetStreamWriteAvailable( PaStream* stream );
-
-/* all callback-related functions are in callback_thread.c */
-extern void *CallbackThread( void *userData );
-
-
-PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
-{
- PaError result = paNoError;
- int i, deviceCount;
- PaAlsaHostApiRepresentation *skeletonHostApi;
-
- skeletonHostApi = (PaAlsaHostApiRepresentation*)
- PaUtil_AllocateMemory( sizeof(PaAlsaHostApiRepresentation) );
- if( !skeletonHostApi )
- {
- result = paInsufficientMemory;
- goto error;
- }
-
- skeletonHostApi->allocations = PaUtil_CreateAllocationGroup();
- if( !skeletonHostApi->allocations )
- {
- result = paInsufficientMemory;
- goto error;
- }
-
- skeletonHostApi->hostApiIndex = hostApiIndex;
- *hostApi = (PaUtilHostApiRepresentation*)skeletonHostApi;
- (*hostApi)->info.structVersion = 1;
- (*hostApi)->info.type = paALSA;
- (*hostApi)->info.name = "ALSA implementation";
-
- BuildDeviceList( skeletonHostApi );
-
- (*hostApi)->Terminate = Terminate;
- (*hostApi)->OpenStream = OpenStream;
-
- PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface,
- CloseStream, StartStream,
- StopStream, AbortStream,
- IsStreamStopped, IsStreamActive,
- GetStreamTime, GetStreamCpuLoad,
- PaUtil_DummyReadWrite, PaUtil_DummyReadWrite,
- PaUtil_DummyGetAvailable,
- PaUtil_DummyGetAvailable );
-
- PaUtil_InitializeStreamInterface( &skeletonHostApi->blockingStreamInterface,
- CloseStream, StartStream,
- StopStream, AbortStream,
- IsStreamStopped, IsStreamActive,
- GetStreamTime, PaUtil_DummyGetCpuLoad,
- ReadStream, WriteStream,
- GetStreamReadAvailable,
- GetStreamWriteAvailable );
-
- return result;
-
-error:
- if( skeletonHostApi )
- {
- if( skeletonHostApi->allocations )
- {
- PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
- PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
- }
-
- PaUtil_FreeMemory( skeletonHostApi );
- }
- return result;
-}
-
-static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
-{
- PaUtilHostApiRepresentation *commonApi = &alsaApi->commonHostApiRep;
- PaDeviceInfo *deviceInfoArray;
- int deviceCount = 0;
- int card_idx;
- int device_idx;
- snd_ctl_t *ctl;
- snd_ctl_card_info_t *card_info;
-
- /* count the devices by enumerating all the card numbers */
-
- /* snd_card_next() modifies the integer passed to it to be:
- * the index of the first card if the parameter is -1
- * the index of the next card if the parameter is the index of a card
- * -1 if there are no more cards
- *
- * The function itself returns 0 if it succeeded. */
- card_idx = -1;
- while( snd_card_next( &card_idx ) == 0 && card_idx >= 0 )
- {
- deviceCount++;
- }
-
- /* allocate deviceInfo memory based on the number of devices */
-
- commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
- alsaApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
- if( !commonApi->deviceInfos )
- {
- return paInsufficientMemory;
- }
-
- /* allocate all device info structs in a contiguous block */
- deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
- alsaApi->allocations, sizeof(PaDeviceInfo) * deviceCount );
- if( !deviceInfoArray )
- {
- return paInsufficientMemory;
- }
-
- /* now loop over the list of devices again, filling in the deviceInfo for each */
- card_idx = -1;
- device_idx = 0;
- while( snd_card_next( &card_idx ) == 0 && card_idx >= 0 )
- {
- PaDeviceInfo *deviceInfo = &deviceInfoArray[device_idx];
- char *deviceName;
- char alsaDeviceName[50];
- const char *cardName;
-
- commonApi->deviceInfos[device_idx++] = deviceInfo;
-
- deviceInfo->structVersion = 2;
- deviceInfo->hostApi = alsaApi->hostApiIndex;
-
- sprintf( alsaDeviceName, "hw:%d", card_idx );
- snd_ctl_open( &ctl, alsaDeviceName, 0 );
- snd_ctl_card_info_malloc( &card_info );
- snd_ctl_card_info( ctl, card_info );
- cardName = snd_ctl_card_info_get_id( card_info );
-
- deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations,
- strlen(cardName) + 1 );
- if( !deviceName )
- {
- return paInsufficientMemory;
- }
- strcpy( deviceName, cardName );
- deviceInfo->name = deviceName;
-
- snd_ctl_card_info_free( card_info );
-
- /* to determine max. channels, we must open the device and query the
- * hardware parameter configuration space */
- {
- snd_pcm_t *pcm_handle;
- snd_pcm_hw_params_t *hw_params;
- int dir;
-
- snd_pcm_hw_params_malloc( &hw_params );
-
- /* get max channels for capture */
-
- if( snd_pcm_open( &pcm_handle, alsaDeviceName, SND_PCM_STREAM_CAPTURE, 0 ) < 0 )
- {
- deviceInfo->maxInputChannels = 0;
- }
- else
- {
- snd_pcm_hw_params_any( pcm_handle, hw_params );
- deviceInfo->maxInputChannels = snd_pcm_hw_params_get_channels_max( hw_params );
- /* TODO: I'm not really sure what to do here */
- //deviceInfo->defaultLowInputLatency = snd_pcm_hw_params_get_period_size_min( hw_params, &dir );
- //deviceInfo->defaultHighInputLatency = snd_pcm_hw_params_get_period_size_max( hw_params, &dir );
- deviceInfo->defaultLowInputLatency = 128. / 44100;
- deviceInfo->defaultHighInputLatency = 16384. / 44100;
- snd_pcm_close( pcm_handle );
- }
-
- /* get max channels for playback */
- if( snd_pcm_open( &pcm_handle, alsaDeviceName, SND_PCM_STREAM_PLAYBACK, 0 ) < 0 )
- {
- deviceInfo->maxOutputChannels = 0;
- }
- else
- {
- snd_pcm_hw_params_any( pcm_handle, hw_params );
- deviceInfo->maxOutputChannels = snd_pcm_hw_params_get_channels_max( hw_params );
- /* TODO: I'm not really sure what to do here */
- //deviceInfo->defaultLowOutputLatency = snd_pcm_hw_params_get_period_size_min( hw_params, &dir );
- //deviceInfo->defaultHighOutputLatency = snd_pcm_hw_params_get_period_size_max( hw_params, &dir );
- deviceInfo->defaultLowOutputLatency = 128. / 44100;
- deviceInfo->defaultHighOutputLatency = 16384. / 44100;
- snd_pcm_close( pcm_handle );
- }
-
- snd_pcm_hw_params_free( hw_params );
- }
-
- deviceInfo->defaultSampleRate = 44100.; /* IMPLEMENT ME */
- }
-
- commonApi->info.deviceCount = deviceCount;
- commonApi->info.defaultInputDevice = 0;
- commonApi->info.defaultOutputDevice = 0;
-
- return paNoError;
-}
-
-
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
-{
- PaAlsaHostApiRepresentation *skeletonHostApi;
- skeletonHostApi = (PaAlsaHostApiRepresentation*)hostApi;
-
- /*
- IMPLEMENT ME:
- - clean up any resourced not handled by the allocation group
- */
-
- if( skeletonHostApi->allocations )
- {
- PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
- PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
- }
-
- PaUtil_FreeMemory( skeletonHostApi );
-}
-
-
-/* Given an open stream, what sample formats are available? */
-
-static PaSampleFormat GetAvailableFormats( snd_pcm_t *stream )
-{
- PaSampleFormat available = 0;
- snd_pcm_hw_params_t *hw_params;
- snd_pcm_hw_params_alloca( &hw_params );
-
- snd_pcm_hw_params_any( stream, hw_params );
-
- if( snd_pcm_hw_params_test_format( stream, hw_params, SND_PCM_FORMAT_FLOAT ) == 0)
- available |= paFloat32;
-
- if( snd_pcm_hw_params_test_format( stream, hw_params, SND_PCM_FORMAT_S16 ) == 0)
- available |= paInt16;
-
- if( snd_pcm_hw_params_test_format( stream, hw_params, SND_PCM_FORMAT_S24 ) == 0)
- available |= paInt24;
-
- if( snd_pcm_hw_params_test_format( stream, hw_params, SND_PCM_FORMAT_S32 ) == 0)
- available |= paInt32;
-
- if( snd_pcm_hw_params_test_format( stream, hw_params, SND_PCM_FORMAT_S8 ) == 0)
- available |= paInt8;
-
- if( snd_pcm_hw_params_test_format( stream, hw_params, SND_PCM_FORMAT_U8 ) == 0)
- available |= paUInt8;
-
- return available;
-}
-
-/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
-
-static PaError ConfigureStream( snd_pcm_t *stream, int channels,
- int interleaved, unsigned long rate,
- PaSampleFormat pa_format, int framesPerBuffer )
-{
-#define ENSURE(functioncall) \
- if( (functioncall) < 0 ) { \
- printf("Error executing ALSA call, line %d\n", __LINE__); \
- return 1; \
- } \
- else { \
- printf("ALSA call at line %d succeeded\n", __LINE__ ); \
- }
-
- snd_pcm_access_t access_mode;
- snd_pcm_format_t alsa_format;
-
- /* configuration consists of setting all of ALSA's parameters.
- * These parameters come in two flavors: hardware parameters
- * and software paramters. Hardware parameters will affect
- * the way the device is initialized, software parameters
- * affect the way ALSA interacts with me, the user-level client. */
-
- snd_pcm_hw_params_t *hw_params;
- snd_pcm_sw_params_t *sw_params;
-
- snd_pcm_hw_params_alloca( &hw_params );
-
- /* ... fill up the configuration space with all possibile
- * combinations of parameters this device will accept */
- ENSURE( snd_pcm_hw_params_any( stream, hw_params ) );
-
- if( interleaved )
- access_mode = SND_PCM_ACCESS_MMAP_INTERLEAVED;
- else
- access_mode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
-
- ENSURE( snd_pcm_hw_params_set_access( stream, hw_params, access_mode ) );
-
- /* set the format based on what the user selected */
- switch( pa_format )
- {
- case paFloat32:
- alsa_format = SND_PCM_FORMAT_FLOAT;
- break;
-
- case paInt16:
- alsa_format = SND_PCM_FORMAT_S16;
- break;
-
- case paInt24:
- alsa_format = SND_PCM_FORMAT_S24;
- break;
-
- case paInt32:
- alsa_format = SND_PCM_FORMAT_S32;
- break;
-
- case paInt8:
- alsa_format = SND_PCM_FORMAT_S8;
- break;
-
- case paUInt8:
- alsa_format = SND_PCM_FORMAT_U8;
- break;
-
- default:
- printf("Unknown PortAudio format %d\n", (int)pa_format );
- return 1;
- }
- //printf("PortAudio format: %d\n", pa_format);
- printf("ALSA format: %d\n", alsa_format);
- ENSURE( snd_pcm_hw_params_set_format( stream, hw_params, alsa_format ) );
-
- /* ... set the sample rate */
- ENSURE( snd_pcm_hw_params_set_rate( stream, hw_params, rate, 0 ) );
-
- /* ... set the number of channels */
- ENSURE( snd_pcm_hw_params_set_channels( stream, hw_params, channels ) );
-
- /* ... set the number of periods to 2, which is essentially double buffering.
- * this makes the latency the number of samples per buffer, which is the best
- * it can be */
- ENSURE( snd_pcm_hw_params_set_periods ( stream, hw_params, 2, 0 ) );
-
- /* ... set the period size, which is essentially the hardware buffer size */
- if( framesPerBuffer != 0 )
- {
- ENSURE( snd_pcm_hw_params_set_period_size( stream, hw_params,
- framesPerBuffer, 0 ) );
- }
- else
- {
- ENSURE( snd_pcm_hw_params_set_period_size( stream, hw_params,
- 2048, 0 ) );
- }
-
-
- /* Set the parameters! */
- ENSURE( snd_pcm_hw_params( stream, hw_params ) );
-
- return 0;
-#undef ENSURE
-}
-
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
- PaStream** s,
- const PaStreamParameters *inputParameters,
- const PaStreamParameters *outputParameters,
- double sampleRate,
- unsigned long framesPerBuffer,
- PaStreamFlags streamFlags,
- PaStreamCallback *callback,
- void *userData )
-{
- PaError result = paNoError;
- PaAlsaHostApiRepresentation *skeletonHostApi =
- (PaAlsaHostApiRepresentation*)hostApi;
- PaAlsaStream *stream = 0;
- PaSampleFormat hostInputSampleFormat=0, hostOutputSampleFormat=0;
- int numInputChannels, numOutputChannels;
- PaSampleFormat inputSampleFormat=0, outputSampleFormat=0;
- unsigned long framesPerHostBuffer = framesPerBuffer;
-
- if( framesPerHostBuffer == paFramesPerBufferUnspecified )
- {
- // TODO: have some reason
- framesPerHostBuffer = 2048;
- }
-
- if( inputParameters )
- {
- numInputChannels = inputParameters->channelCount;
- inputSampleFormat = inputParameters->sampleFormat;
-
- /* unless alternate device specification is supported, reject the use of
- paUseHostApiSpecificDeviceSpecification.
- [JH] this could be supported in the future, to allow ALSA device strings
- like hw:0 */
- if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
- return paInvalidDevice;
-
- /* check that input device can support numInputChannels */
- if( numInputChannels > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
- return paInvalidChannelCount;
-
- /* validate inputStreamInfo */
- if( inputParameters->hostApiSpecificStreamInfo )
- return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
- }
- else
- {
- numInputChannels = 0;
- }
-
- if( outputParameters )
- {
- numOutputChannels = outputParameters->channelCount;
- outputSampleFormat = outputParameters->sampleFormat;
-
- /* unless alternate device specification is supported, reject the use of
- paUseHostApiSpecificDeviceSpecification
- [JH] this could be supported in the future, to allow ALSA device strings
- like hw:0 */
-
- if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
- return paInvalidDevice;
-
- /* check that output device can support numInputChannels */
- if( numOutputChannels > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
- return paInvalidChannelCount;
-
- /* validate outputStreamInfo */
- if( outputParameters->hostApiSpecificStreamInfo )
- return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
- }
- else
- {
- numOutputChannels = 0;
- }
-
- /* validate platform specific flags */
- if( (streamFlags & paPlatformSpecificFlags) != 0 )
- return paInvalidFlag; /* unexpected platform specific flag */
-
- /* allocate and do basic initialization of the stream structure */
-
- stream = (PaAlsaStream*)PaUtil_AllocateMemory( sizeof(PaAlsaStream) );
- if( !stream )
- {
- printf("memory point 2\n");
- result = paInsufficientMemory;
- goto error;
- }
-
- stream->pcm_capture = NULL;
- stream->pcm_playback = NULL;
- stream->callback_mode = (callback != 0);
- stream->callback_finished = 0;
-
- if( callback )
- {
- PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
- &skeletonHostApi->callbackStreamInterface,
- callback, userData );
- }
- else
- {
- PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
- &skeletonHostApi->blockingStreamInterface,
- callback, userData );
- }
-
-
- stream->streamRepresentation.streamInfo.inputLatency = framesPerHostBuffer;
- stream->streamRepresentation.streamInfo.outputLatency = framesPerHostBuffer;
- stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
-
- PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
-
- /* open the devices now, so we can obtain info about the available formats */
-
- if( numInputChannels > 0 )
- {
- char inputDeviceName[50];
-
- sprintf( inputDeviceName, "hw:CARD=%s", hostApi->deviceInfos[inputParameters->device]->name );
- if( snd_pcm_open( &stream->pcm_capture, inputDeviceName, SND_PCM_STREAM_CAPTURE, 0 ) < 0 )
- {
- result = paBadIODeviceCombination;
- goto error;
- }
- hostInputSampleFormat =
- PaUtil_SelectClosestAvailableFormat( GetAvailableFormats(stream->pcm_capture),
- inputSampleFormat );
- }
-
- if( numOutputChannels > 0 )
- {
- char outputDeviceName[50];
-
- sprintf( outputDeviceName, "hw:CARD=%s", hostApi->deviceInfos[outputParameters->device]->name );
- if( snd_pcm_open( &stream->pcm_playback, outputDeviceName, SND_PCM_STREAM_PLAYBACK, 0 ) < 0 )
- {
- result = paBadIODeviceCombination;
- goto error;
- }
- hostOutputSampleFormat =
- PaUtil_SelectClosestAvailableFormat( GetAvailableFormats(stream->pcm_playback),
- outputSampleFormat );
- stream->playback_hostsampleformat = hostOutputSampleFormat;
- }
-
-
-
- result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
- numInputChannels, inputSampleFormat, hostInputSampleFormat,
- numOutputChannels, outputSampleFormat, hostOutputSampleFormat,
- sampleRate, streamFlags, framesPerBuffer, framesPerHostBuffer,
- paUtilFixedHostBufferSize, callback, userData );
- if( result != paNoError )
- goto error;
-
- /* configure the streams */
-
- if( numInputChannels > 0 )
- {
- int interleaved;
- PaSampleFormat plain_format = hostInputSampleFormat & ~paNonInterleaved;
-
- if( inputSampleFormat & paNonInterleaved )
- interleaved = 0;
- else
- interleaved = 1;
-
- if( ConfigureStream( stream->pcm_capture, numInputChannels, interleaved,
- sampleRate, plain_format, framesPerHostBuffer ) != 0 )
- {
- result = paBadIODeviceCombination;
- goto error;
- }
-
- stream->capture_interleaved = interleaved;
- }
-
- if( numOutputChannels > 0 )
- {
- int interleaved;
- PaSampleFormat plain_format = hostOutputSampleFormat & ~paNonInterleaved;
-
- if( outputSampleFormat & paNonInterleaved )
- interleaved = 0;
- else
- interleaved = 1;
-
- if( ConfigureStream( stream->pcm_playback, numOutputChannels, interleaved,
- sampleRate, plain_format, framesPerHostBuffer ) != 0 )
- {
- result = paBadIODeviceCombination;
- goto error;
- }
-
- stream->playback_interleaved = interleaved;
- }
-
- stream->capture_nfds = 0;
- stream->playback_nfds = 0;
-
- if( stream->pcm_capture )
- stream->capture_nfds = snd_pcm_poll_descriptors_count( stream->pcm_capture );
-
- if( stream->pcm_playback )
- stream->playback_nfds = snd_pcm_poll_descriptors_count( stream->pcm_playback );
-
- /* TODO: free this properly */
- printf("trying to allocate %d bytes of memory\n", (stream->capture_nfds + stream->playback_nfds + 1) * sizeof(struct pollfd) );
- stream->pfds = (struct pollfd*)PaUtil_AllocateMemory( (stream->capture_nfds +
- stream->playback_nfds + 1) *
- sizeof(struct pollfd) );
- if( !stream->pfds )
- {
- printf("bad memory point 1\n");
- result = paInsufficientMemory;
- goto error;
- }
-
- stream->frames_per_period = framesPerHostBuffer;
- stream->capture_channels = numInputChannels;
- stream->playback_channels = numOutputChannels;
-
- *s = (PaStream*)stream;
-
- return result;
-
-error:
- if( stream )
- PaUtil_FreeMemory( stream );
-
- return result;
-}
-
-
-/*
- When CloseStream() is called, the multi-api layer ensures that
- the stream has already been stopped or aborted.
-*/
-static PaError CloseStream( PaStream* s )
-{
- PaError result = paNoError;
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- if( stream->pcm_capture )
- {
- snd_pcm_close( stream->pcm_capture );
- }
-
- if( stream->pcm_playback )
- {
- snd_pcm_close( stream->pcm_playback );
- }
-
- PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
- PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
- PaUtil_FreeMemory( stream );
-
- return result;
-}
-
-
-static PaError StartStream( PaStream *s )
-{
- PaError result = paNoError;
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- /* TODO: support errorText */
-#define ENSURE(x) \
- { \
- int error_ret; \
- error_ret = (x); \
- if( error_ret != 0 ) { \
- PaHostErrorInfo err; \
- err.errorCode = error_ret; \
- err.hostApiType = paALSA; \
- printf("call at %d failed\n", __LINE__); \
- return paUnanticipatedHostError; \
- } \
- else \
- printf("call at line %d succeeded\n", __LINE__); \
- }
-
- if( stream->pcm_capture )
- {
- ENSURE( snd_pcm_prepare( stream->pcm_capture ) );
- }
-
- if( stream->pcm_playback )
- {
- const snd_pcm_channel_area_t *playback_areas, *area;
- snd_pcm_uframes_t offset, frames;
- int sample_size = Pa_GetSampleSize( stream->playback_hostsampleformat );
- printf("Sample size: %d\n", sample_size );
- ENSURE( snd_pcm_prepare( stream->pcm_playback ) );
- frames = snd_pcm_avail_update( stream->pcm_playback );
- printf("frames: %d\n", (int)frames );
- printf("channels: %d\n", stream->playback_channels );
-
- snd_pcm_mmap_begin( stream->pcm_playback, &playback_areas, &offset, &frames );
-
- /* Insert silence */
- if( stream->playback_interleaved )
- {
- void *playback_buffer;
- area = &playback_areas[0];
- playback_buffer = area->addr + (area->first + area->step * offset) / 8;
- memset( playback_buffer, 0,
- frames * stream->playback_channels * sample_size );
- }
- else
- {
- int i;
- for( i = 0; i < stream->playback_channels; i++ )
- {
- void *channel_buffer;
- area = &playback_areas[i];
- channel_buffer = area->addr + (area->first + area->step * offset) / 8;
- memset( channel_buffer, 0, frames * sample_size );
- }
- }
-
- snd_pcm_mmap_commit( stream->pcm_playback, offset, frames );
- }
-
- if( stream->callback_mode )
- {
- ENSURE( pthread_create( &stream->callback_thread, NULL, &CallbackThread, stream ) );
-
- /* we'll do the snd_pcm_start() in the callback thread */
- }
- else
- {
- if( stream->pcm_capture )
- snd_pcm_start( stream->pcm_capture );
- if( stream->pcm_playback )
- snd_pcm_start( stream->pcm_playback );
- }
-
- /* On my machine, the pcm stream will not transition to the RUNNING
- * state for a while after snd_pcm_start is called. The PortAudio
- * client needs to be able to depend on Pa_IsStreamActive() returning
- * true the second after this function returns. So I sleep briefly here.
- *
- * I don't like this one bit.
- */
- Pa_Sleep( 100 );
-
- stream->callback_finished = 0;
-
- return result;
-}
-
-
-static PaError StopStream( PaStream *s )
-{
- PaError result = paNoError;
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- /* First deal with the callback thread, cancelling and/or joining
- * it if necessary
- */
-
- if( stream->callback_mode && stream->callback_finished )
- {
- /* We are running in callback mode but the callback thread has
- * already been cancelled by the return value from the user's
- * callback function. Therefore we don't need to cancel the
- * thread, but we do want to wait for it. */
- pthread_join( stream->callback_thread, NULL );
- }
- else if( stream->callback_mode )
- {
- /* We are running in callback mode, and the callback thread
- * is still running. Cancel it and wait for it to be done. */
- pthread_cancel( stream->callback_thread );
- pthread_join( stream->callback_thread, NULL );
- }
-
- /* Stop the ALSA streams if necessary */
-
- if( stream->callback_mode && stream->callback_finished )
- {
- /* If we are in the callback_finished state the callback thread
- * already stopped the streams. So there is nothing to do here.
- */
- }
- else
- {
- if( stream->pcm_capture )
- {
- snd_pcm_drain( stream->pcm_capture );
- }
-
- if( stream->pcm_playback )
- {
- snd_pcm_drain( stream->pcm_playback );
- }
- }
-
- stream->callback_finished = 0;
-
- return result;
-}
-
-
-static PaError AbortStream( PaStream *s )
-{
- PaError result = paNoError;
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- /* First deal with the callback thread, cancelling and/or joining
- * it if necessary
- */
-
- if( stream->callback_mode && stream->callback_finished )
- {
- /* We are running in callback mode but the callback thread has
- * already been cancelled by the return value from the user's
- * callback function. Therefore we don't need to cancel the
- * thread, but we do want to wait for it. */
- pthread_join( stream->callback_thread, NULL );
- }
- else if( stream->callback_mode )
- {
- /* We are running in callback mode, and the callback thread
- * is still running. Cancel it and wait for it to be done. */
- pthread_cancel( stream->callback_thread );
- pthread_join( stream->callback_thread, NULL );
- }
-
- /* Stop the ALSA streams if necessary */
-
- if( stream->callback_mode && stream->callback_finished )
- {
- /* If we are in the callback_finished state the callback thread
- * already stopped the streams. So there is nothing to do here.
- */
- }
- else
- {
- if( stream->pcm_capture )
- {
- snd_pcm_drop( stream->pcm_capture );
- }
-
- if( stream->pcm_playback )
- {
- snd_pcm_drop( stream->pcm_playback );
- }
- }
-
- stream->callback_finished = 0;
-
- return result;
-}
-
-
-static PaError IsStreamStopped( PaStream *s )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- if( IsStreamActive(s) || stream->callback_finished )
- return 0;
- else
- return 1;
-}
-
-
-static PaError IsStreamActive( PaStream *s )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- if( stream->pcm_capture )
- {
- snd_pcm_state_t capture_state = snd_pcm_state( stream->pcm_capture );
-
- if( capture_state == SND_PCM_STATE_RUNNING /*||
- capture_state == SND_PCM_STATE_PREPARED*/ )
- return 1;
- }
-
- if( stream->pcm_playback )
- {
- snd_pcm_state_t playback_state = snd_pcm_state( stream->pcm_playback );
-
- if( playback_state == SND_PCM_STATE_RUNNING /*||
- playback_state == SND_PCM_STATE_PREPARED*/ )
- return 1;
- }
-
- return 0;
-}
-
-
-static PaTime GetStreamTime( PaStream *s )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- snd_output_t *output;
- snd_timestamp_t timestamp;
- snd_pcm_status_t *status;
- snd_pcm_status_alloca( &status );
-
- /* TODO: what if we have both? does it really matter? */
-
- /* TODO: if running in callback mode, this will mean
- * libasound routines are being called form multiple threads.
- * need to verify that libasound is thread-safe. */
-
- if( stream->pcm_capture )
- {
- snd_pcm_status( stream->pcm_capture, status );
- }
- else if( stream->pcm_playback )
- {
- snd_pcm_status( stream->pcm_playback, status );
- }
-
- snd_pcm_status_get_tstamp( status, &timestamp );
-
- return timestamp.tv_sec + ((float)timestamp.tv_usec/1000000);
-}
-
-
-static double GetStreamCpuLoad( PaStream* s )
-{
- PaAlsaStream *stream = (PaAlsaStream*)s;
-
- return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
-}
-
diff --git a/pd/portaudio/pa_linux_alsa/pa_linux_alsa.h b/pd/portaudio/pa_linux_alsa/pa_linux_alsa.h
deleted file mode 100644
index 62c9512c..00000000
--- a/pd/portaudio/pa_linux_alsa/pa_linux_alsa.h
+++ /dev/null
@@ -1,45 +0,0 @@
-
-#include <alsa/asoundlib.h>
-
-#include <pthread.h>
-
-#include "pa_util.h"
-#include "pa_process.h"
-#include "pa_cpuload.h"
-#include "pa_stream.h"
-
-typedef struct PaAlsaStream
-{
- PaUtilStreamRepresentation streamRepresentation;
- PaUtilCpuLoadMeasurer cpuLoadMeasurer;
- PaUtilBufferProcessor bufferProcessor;
-
- snd_pcm_t *pcm_capture;
- snd_pcm_t *pcm_playback;
-
- int callback_finished; /* bool: are we in the "callback finished" state? */
-
- int frames_per_period;
- int playback_hostsampleformat;
-
- int capture_channels;
- int playback_channels;
-
- int capture_interleaved; /* bool: is capture interleaved? */
- int playback_interleaved; /* bool: is playback interleaved? */
-
- int callback_mode; /* bool: are we running in callback mode? */
- pthread_t callback_thread;
-
- /* the callback thread uses these to poll the sound device, waiting
- * for data to be ready/available */
- unsigned int capture_nfds;
- unsigned int playback_nfds;
- struct pollfd *pfds;
-
- /* these aren't really stream state, the callback uses them */
- snd_pcm_uframes_t capture_offset;
- snd_pcm_uframes_t playback_offset;
-}
-PaAlsaStream;
-