Browse Source

[0.99.44] ALSA driver bug fixes:

+ format search problem introduced yesterday
  + bug:00031 "crash when using more than 32 channels"


git-svn-id: svn+ssh://jackaudio.org/trunk/jack@864 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
joq 21 years ago
parent
commit
5d38699f39
5 changed files with 170 additions and 38 deletions
  1. +1
    -1
      configure.ac
  2. +14
    -12
      drivers/alsa/alsa_driver.c
  3. +42
    -25
      drivers/alsa/alsa_driver.h
  4. +1
    -0
      jack/Makefile.am
  5. +112
    -0
      jack/bitset.h

+ 1
- 1
configure.ac View File

@@ -15,7 +15,7 @@ dnl changes are made
dnl ---
JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=99
JACK_MICRO_VERSION=43
JACK_MICRO_VERSION=44

dnl ---
dnl HOWTO: updating the jack protocol version


+ 14
- 12
drivers/alsa/alsa_driver.c View File

@@ -58,6 +58,9 @@ extern void show_work_times ();
static void
alsa_driver_release_channel_dependent_memory (alsa_driver_t *driver)
{
bitset_destroy (&driver->channels_done);
bitset_destroy (&driver->channels_not_done);

if (driver->playback_addr) {
free (driver->playback_addr);
driver->playback_addr = 0;
@@ -340,7 +343,8 @@ alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name,
snd_pcm_hw_params_t *hw_params,
snd_pcm_sw_params_t *sw_params,
unsigned int *nperiodsp,
unsigned long *nchns,unsigned long sample_width)
unsigned long *nchns,
unsigned long sample_width)
{
int err, format;
unsigned int frame_rate;
@@ -387,9 +391,9 @@ alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name,
if ((err = snd_pcm_hw_params_set_format (
handle, hw_params, formats[format].format)) < 0) {
int failed_format = format;
if (sample_width == (4
? format++ < NOFORMATS - 1
: format-- > 0)) {
if ((sample_width == 4
? format++ < NOFORMATS - 1
: format-- > 0)) {
jack_error ("Couldn't open %s for %s samples"
" trying %s instead", device_name,
formats[failed_format].Name,
@@ -806,12 +810,10 @@ alsa_driver_set_parameters (alsa_driver_t *driver,
channels require action on every cycle. any bits that are
not set after the engine's process() call indicate channels
that potentially need to be silenced.

XXX this is limited to <wordsize> channels. Use a bitset
type instead.
*/

driver->channel_done_bits = 0;
bitset_create (&driver->channels_done, driver->max_nchannels);
bitset_create (&driver->channels_not_done, driver->max_nchannels);

if (driver->playback_handle) {
driver->playback_addr = (char **)
@@ -827,7 +829,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver,
}

for (chn = 0; chn < driver->playback_nchannels; chn++) {
driver->channel_done_bits |= (1<<chn);
bitset_add (driver->channels_done, chn);
}

driver->dither_state = (dither_state_t *)
@@ -1148,7 +1150,7 @@ alsa_driver_silence_untouched_channels (alsa_driver_t *driver,
driver->frames_per_cycle * driver->playback_nperiods;

for (chn = 0; chn < driver->playback_nchannels; chn++) {
if ((driver->channels_not_done & (1<<chn))) {
if (bitset_contains (driver->channels_not_done, chn)) {
if (driver->silent[chn] < buffer_frames) {
alsa_driver_silence_on_channel_no_mark (
driver, chn, nframes);
@@ -1414,7 +1416,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float

/* mark all channels not done for now. read/write will change this */

driver->channels_not_done = driver->channel_done_bits;
bitset_copy (driver->channels_not_done, driver->channels_done);

/* constrain the available count to the nearest (round down) number of
periods.
@@ -1622,7 +1624,7 @@ alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes)
buf + nwritten, contiguous);
}

if (driver->channels_not_done) {
if (!bitset_empty (driver->channels_not_done)) {
alsa_driver_silence_untouched_channels (driver,
contiguous);
}


+ 42
- 25
drivers/alsa/alsa_driver.h View File

@@ -22,6 +22,7 @@
#define __jack_alsa_driver_h__

#include <alsa/asoundlib.h>
#include <jack/bitset.h>

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define SND_PCM_FORMAT_S24_3 SND_PCM_FORMAT_S24_3LE
@@ -82,8 +83,8 @@ typedef struct _alsa_driver {
char *alsa_name_playback;
char *alsa_name_capture;
char *alsa_driver;
unsigned long channels_not_done;
unsigned long channel_done_bits;
bitset_t channels_not_done;
bitset_t channels_done;
snd_pcm_format_t playback_sample_format;
snd_pcm_format_t capture_sample_format;
float max_sample_val;
@@ -139,12 +140,15 @@ typedef struct _alsa_driver {

} alsa_driver_t;

static __inline__ void alsa_driver_mark_channel_done (alsa_driver_t *driver, channel_t chn) {
driver->channels_not_done &= ~(1<<chn);
static inline void
alsa_driver_mark_channel_done (alsa_driver_t *driver, channel_t chn) {
bitset_remove (driver->channels_not_done, chn);
driver->silent[chn] = 0;
}

static __inline__ void alsa_driver_silence_on_channel (alsa_driver_t *driver, channel_t chn, jack_nframes_t nframes) {
static inline void
alsa_driver_silence_on_channel (alsa_driver_t *driver, channel_t chn,
jack_nframes_t nframes) {
if (driver->playback_interleaved) {
memset_interleave
(driver->playback_addr[chn],
@@ -152,12 +156,15 @@ static __inline__ void alsa_driver_silence_on_channel (alsa_driver_t *driver, ch
driver->interleave_unit,
driver->playback_interleave_skip);
} else {
memset (driver->playback_addr[chn], 0, nframes * driver->playback_sample_bytes);
memset (driver->playback_addr[chn], 0,
nframes * driver->playback_sample_bytes);
}
alsa_driver_mark_channel_done (driver,chn);
}

static __inline__ void alsa_driver_silence_on_channel_no_mark (alsa_driver_t *driver, channel_t chn, jack_nframes_t nframes) {
static inline void
alsa_driver_silence_on_channel_no_mark (alsa_driver_t *driver, channel_t chn,
jack_nframes_t nframes) {
if (driver->playback_interleaved) {
memset_interleave
(driver->playback_addr[chn],
@@ -165,13 +172,16 @@ static __inline__ void alsa_driver_silence_on_channel_no_mark (alsa_driver_t *dr
driver->interleave_unit,
driver->playback_interleave_skip);
} else {
memset (driver->playback_addr[chn], 0, nframes * driver->playback_sample_bytes);
memset (driver->playback_addr[chn], 0,
nframes * driver->playback_sample_bytes);
}
}

static __inline__ void alsa_driver_read_from_channel (alsa_driver_t *driver,
channel_t channel, jack_default_audio_sample_t *buf,
jack_nframes_t nsamples)
static inline void
alsa_driver_read_from_channel (alsa_driver_t *driver,
channel_t channel,
jack_default_audio_sample_t *buf,
jack_nframes_t nsamples)
{
driver->read_via_copy (buf,
driver->capture_addr[channel],
@@ -179,10 +189,11 @@ static __inline__ void alsa_driver_read_from_channel (alsa_driver_t *driver,
driver->capture_interleave_skip);
}

static __inline__ void alsa_driver_write_to_channel (alsa_driver_t *driver,
channel_t channel,
jack_default_audio_sample_t *buf,
jack_nframes_t nsamples)
static inline void
alsa_driver_write_to_channel (alsa_driver_t *driver,
channel_t channel,
jack_default_audio_sample_t *buf,
jack_nframes_t nsamples)
{
driver->write_via_copy (driver->playback_addr[channel],
buf,
@@ -192,10 +203,11 @@ static __inline__ void alsa_driver_write_to_channel (alsa_driver_t *driver,
alsa_driver_mark_channel_done (driver, channel);
}

static __inline__ void alsa_driver_copy_channel (alsa_driver_t *driver,
channel_t input_channel,
channel_t output_channel,
jack_nframes_t nsamples) {
static inline void
alsa_driver_copy_channel (alsa_driver_t *driver,
channel_t input_channel,
channel_t output_channel,
jack_nframes_t nsamples) {

driver->channel_copy (driver->playback_addr[output_channel],
driver->capture_addr[input_channel],
@@ -205,11 +217,16 @@ static __inline__ void alsa_driver_copy_channel (alsa_driver_t *driver,
alsa_driver_mark_channel_done (driver, output_channel);
}

void alsa_driver_silence_untouched_channels (alsa_driver_t *driver, jack_nframes_t nframes);
void alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn, ClockSyncStatus status);
int alsa_driver_listen_for_clock_sync_status (alsa_driver_t *, ClockSyncListenerFunction, void *arg);
int alsa_driver_stop_listen_for_clock_sync_status (alsa_driver_t *, unsigned int);
void alsa_driver_clock_sync_notify (alsa_driver_t *, channel_t chn, ClockSyncStatus);

void alsa_driver_silence_untouched_channels (alsa_driver_t *driver,
jack_nframes_t nframes);
void alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn,
ClockSyncStatus status);
int alsa_driver_listen_for_clock_sync_status (alsa_driver_t *,
ClockSyncListenerFunction,
void *arg);
int alsa_driver_stop_listen_for_clock_sync_status (alsa_driver_t *,
unsigned int);
void alsa_driver_clock_sync_notify (alsa_driver_t *, channel_t chn,
ClockSyncStatus);

#endif /* __jack_alsa_driver_h__ */

+ 1
- 0
jack/Makefile.am View File

@@ -14,6 +14,7 @@ libjackinclude_HEADERS = \

noinst_HEADERS = \
atomicity.h \
bitset.h \
driver.h \
driver_interface.h \
driver_parse.h \


+ 112
- 0
jack/bitset.h View File

@@ -0,0 +1,112 @@
/*
* bitset.h -- some simple bit vector set operations.
*
* This is useful for sets of small non-negative integers. There are
* some obvious set operations that are not implemented because I
* don't need them right now.
*
* These functions represent sets as arrays of unsigned 32-bit
* integers allocated on the heap. The first entry contains the set
* cardinality (number of elements allowed), followed by one or more
* words containing bit vectors.
*
* $Id$
*/

/*
* Copyright (C) 2005 Jack O'Quin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __bitset_h__
#define __bitset_h__

#include <inttypes.h> /* POSIX standard fixed-size types */
#include <assert.h> /* `#define NDEBUG' to disable */

/* On some 64-bit machines, this implementation may be slightly
* inefficient, depending on how compilers allocate space for
* uint32_t. For the set sizes I currently need, this is acceptable.
* It should not be hard to pack the bits better, if that becomes
* worthwhile.
*/
typedef uint32_t _bitset_word_t;
typedef _bitset_word_t *bitset_t;

#define WORD_SIZE(cardinality) (1+((cardinality)+31)/32)
#define BYTE_SIZE(cardinality) (WORD_SIZE(cardinality)*sizeof(_bitset_word_t))
#define WORD_INDEX(element) (1+(element)/32)
#define BIT_INDEX(element) ((element)&037)

static inline void
bitset_add(bitset_t set, unsigned int element)
{
assert(element < set[0]);
set[WORD_INDEX(element)] |= (1 << BIT_INDEX(element));
}

static inline void
bitset_copy(bitset_t to_set, bitset_t from_set)
{
assert(to_set[0] == from_set[0]);
memcpy(to_set, from_set, BYTE_SIZE(to_set[0]));
}

static inline void
bitset_create(bitset_t *set, unsigned int cardinality)
{
*set = (bitset_t) calloc(WORD_SIZE(cardinality),
sizeof(_bitset_word_t));
assert(*set);
*set[0] = cardinality;
}

static inline void
bitset_destroy(bitset_t *set)
{
if (*set) {
free(*set);
*set = (bitset_t) 0;
}
}

static inline int
bitset_empty(bitset_t set)
{
int i;
_bitset_word_t result = 0;
int nwords = WORD_SIZE(set[0]);
for (i = 1; i < nwords; i++) {
result |= set[i];
}
return (result == 0);
}

static inline int
bitset_contains(bitset_t set, unsigned int element)
{
assert(element < set[0]);
return (0 != (set[WORD_INDEX(element)] & (1<<BIT_INDEX(element))));
}

static inline void
bitset_remove(bitset_t set, unsigned int element)
{
assert(element < set[0]);
set[WORD_INDEX(element)] &= ~(1<<BIT_INDEX(element));
}

#endif /* __bitset_h__ */

Loading…
Cancel
Save