+ 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-9f06e86f4224tags/0.109.0
| @@ -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 | |||
| @@ -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); | |||
| } | |||
| @@ -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__ */ | |||
| @@ -14,6 +14,7 @@ libjackinclude_HEADERS = \ | |||
| noinst_HEADERS = \ | |||
| atomicity.h \ | |||
| bitset.h \ | |||
| driver.h \ | |||
| driver_interface.h \ | |||
| driver_parse.h \ | |||
| @@ -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__ */ | |||