On Sun, Mar 12, 2006 at 02:36:21PM -0500, Robert McGwier wrote: > That is why I put the message out. It will be good to have a working > starting point.
Okay, there it is. Just checked in to gr-audio-portaudio repository. It's somewhat working, but there's still some static in the audio output (tested with ALSA playback, mono and stereo). Some more work is needed. You will need the attached patchs: - against gnuradio-core: ot_gri_ringbuffer.patch * src/lib/omnithread/omnithread.h: add omni_mutex::trylock * src/lib/general/gri_ringbuffer.{cc,h}, src/lib/general/Makefile.am: new lockless ringbuffer (single reader/single writer) taken from JACK software (GPL). - against portaudio-V19(CVS): portaudio-pkg-config.patch * pkg-config .pc file with proper THREAD_FLAGS The code should be portable. I was missing the native Win32 call for mutex_trylock, so someone will have to find it, and define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION in src/lib/omnithread/ot_nt.h, with appropriate semantic (return value). The gri_pa_find_device_by_name() function will have to be made more smart, like accepting which HostApi (ALSA, JACK, ..) is to be chosen, and which device from this API. A syntax will have to be agreed upon, like "ALSA:hw:0" or "OSS:/dev/dsp1". Have fun, -- Stephane
Index: src/lib/general/Makefile.am =================================================================== RCS file: /sources/gnuradio/gnuradio-core/src/lib/general/Makefile.am,v retrieving revision 1.83 diff -u -b -B -w -p -r1.83 Makefile.am --- src/lib/general/Makefile.am 23 Feb 2006 21:26:29 -0000 1.83 +++ src/lib/general/Makefile.am 12 Mar 2006 20:55:14 -0000 @@ -187,6 +187,7 @@ libgeneral_la_SOURCES = \ gri_char_to_float.cc \ gri_uchar_to_float.cc \ gri_interleaved_short_to_complex.cc \ + gri_ringbuffer.cc \ malloc16.c libgeneral_qa_la_SOURCES = \ @@ -302,6 +303,7 @@ grinclude_HEADERS = \ gri_lfsr_32k.h \ gri_short_to_float.h \ gri_char_to_float.h \ + gri_ringbuffer.h \ gri_uchar_to_float.h \ random.h Index: src/lib/omnithread/omnithread.h =================================================================== RCS file: /sources/gnuradio/gnuradio-core/src/lib/omnithread/omnithread.h,v retrieving revision 1.1.1.1 diff -u -b -B -w -p -r1.1.1.1 omnithread.h --- src/lib/omnithread/omnithread.h 10 Apr 2004 18:00:52 -0000 1.1.1.1 +++ src/lib/omnithread/omnithread.h 12 Mar 2006 20:55:19 -0000 @@ -145,6 +145,7 @@ class omni_thread; #if (!defined(OMNI_MUTEX_IMPLEMENTATION) || \ !defined(OMNI_MUTEX_LOCK_IMPLEMENTATION) || \ + !defined(OMNI_MUTEX_TRYLOCK_IMPLEMENTATION)|| \ !defined(OMNI_MUTEX_UNLOCK_IMPLEMENTATION) || \ !defined(OMNI_CONDITION_IMPLEMENTATION) || \ !defined(OMNI_SEMAPHORE_IMPLEMENTATION) || \ @@ -186,6 +187,10 @@ public: inline void lock(void) { OMNI_MUTEX_LOCK_IMPLEMENTATION } inline void unlock(void) { OMNI_MUTEX_UNLOCK_IMPLEMENTATION } + inline int trylock(void) { return OMNI_MUTEX_TRYLOCK_IMPLEMENTATION } + // if mutex is unlocked, lock it and return 1 (true). + // If it's already locked then return 0 (false). + inline void acquire(void) { lock(); } inline void release(void) { unlock(); } // the names lock and unlock are preferred over acquire and release Index: src/lib/omnithread/ot_posix.h =================================================================== RCS file: /sources/gnuradio/gnuradio-core/src/lib/omnithread/ot_posix.h,v retrieving revision 1.1.1.1 diff -u -b -B -w -p -r1.1.1.1 ot_posix.h --- src/lib/omnithread/ot_posix.h 10 Apr 2004 18:00:52 -0000 1.1.1.1 +++ src/lib/omnithread/ot_posix.h 12 Mar 2006 20:55:19 -0000 @@ -57,6 +57,9 @@ extern "C" void* omni_thread_wrapper(voi #define OMNI_MUTEX_LOCK_IMPLEMENTATION \ pthread_mutex_lock(&posix_mutex); +#define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION \ + pthread_mutex_trylock(&posix_mutex); + #define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ pthread_mutex_unlock(&posix_mutex); --- /dev/null 2006-03-10 00:02:48.821312048 +0100 +++ src/lib/general/gri_ringbuffer.h 2006-03-12 20:05:46.000000000 +0100 @@ -0,0 +1,203 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * + * Most code from this file is taken from file ringbuffer.c of JACK project. + * Original code was written by Paul Davis and Rohan Drape. + * + * ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code. + * This is safe for the case of one read thread and one write thread. + */ + + +#ifndef _GRI_RINGBUFFER_H +#define _GRI_RINGBUFFER_H + +#include <sys/types.h> + +/** @file gri_ringbuffer.h + * + * A set of library functions to make lock-free ringbuffers available + * to GNU Radio applications. + * + * The key attribute of a ringbuffer is that it can be safely accessed + * by two threads simultaneously -- one reading from the buffer and + * the other writing to it -- without using any synchronization or + * mutual exclusion primitives. For this to work correctly, there can + * only be a single reader and a single writer thread. Their + * identities cannot be interchanged. + */ + +class gri_ringbuffer { + char *d_buf; + volatile size_t d_write_ptr; + volatile size_t d_read_ptr; + size_t d_size; + size_t d_size_mask; + int d_mlocked; +public: + + typedef struct + { + char *buf; + size_t len; + } datavec_t; + + /** + * @param sz the ringbuffer size in bytes. + */ + gri_ringbuffer(size_t sz); + + virtual ~gri_ringbuffer (); + + /** + * Fill a data structure with a description of the current readable + * data held in the ringbuffer. This description is returned in a two + * element array of datavec_t. Two elements are needed + * because the data to be read may be split across the end of the + * ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be read in a contiguous fashion using the address given in the + * corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be read from the address given in + * its corresponding @a buf field. + * + * @param vec a pointer to a 2 element array of datavec_t. + * + */ + void get_read_vector(datavec_t *vec); + + /** + * Fill a data structure with a description of the current writable + * space in the ringbuffer. The description is returned in a two + * element array of datavec_t. Two elements are needed + * because the space available for writing may be split across the end + * of the ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be written in a contiguous fashion using the address given in + * the corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be written to the address given in + * the corresponding @a buf field. + * + * @param vec a pointer to a 2 element array of datavec_t. + */ + void get_write_vector(datavec_t *vec); + + /** + * Read data from the ringbuffer. + * + * @param dest a pointer to a buffer where data read from the + * ringbuffer will go. + * @param cnt the number of bytes to read. + * + * @return the number of bytes read, which may range from 0 to cnt. + */ + size_t read(char *dest, size_t cnt); + + /** + * Read data from the ringbuffer. Opposed to read() + * this function does not move the read pointer. Thus it's + * a convenient way to inspect data in the ringbuffer in a + * continous fashion. The price is that the data is copied + * into a user provided buffer. For "raw" non-copy inspection + * of the data in the ringbuffer use get_read_vector(). + * + * @param dest a pointer to a buffer where data read from the + * ringbuffer will go. + * @param cnt the number of bytes to read. + * + * @return the number of bytes read, which may range from 0 to cnt. + */ + size_t peek(char *dest, size_t cnt); + + /** + * Advance the read pointer. + * + * After data have been read from the ringbuffer using the pointers + * returned by get_read_vector(), use this function to + * advance the buffer pointers, making that space available for future + * write operations. + * + * @param cnt the number of bytes read. + */ + void read_advance(size_t cnt); + + /** + * Return the number of bytes available for reading. + * + * @return the number of bytes available to read. + */ + size_t read_space(void); + + /** + * Lock a ringbuffer data block into memory. + * + * Uses the mlock() system call. This is not a realtime operation. + */ + int mlock(void); + + /** + * Reset the read and write pointers, making an empty buffer. + * + * This is not thread safe. + */ + void reset(void); + + /** + * Write data into the ringbuffer. + * + * @param src a pointer to the data to be written to the ringbuffer. + * @param cnt the number of bytes to write. + * + * @return the number of bytes write, which may range from 0 to cnt + */ + size_t write(const char *src, size_t cnt); + + /** + * Advance the write pointer. + * + * After data have been written the ringbuffer using the pointers + * returned by get_write_vector(), use this function + * to advance the buffer pointer, making the data available for future + * read operations. + * + * @param cnt the number of bytes written. + */ + void write_advance(size_t cnt); + + /** + * Return the number of bytes available for writing. + * + * @return the amount of free space (in bytes) available for writing. + */ + size_t write_space(void); + +}; + +#endif --- /dev/null 2006-03-10 00:02:48.821312048 +0100 +++ src/lib/general/gri_ringbuffer.cc 2006-03-11 23:09:35.000000000 +0100 @@ -0,0 +1,362 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * + * Most code from this file is derivated from file ringbuffer.c of JACK software. + * Original code was written by Paul Davis and Rohan Drape. + * + * ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code. + * This is safe for the case of one read thread and one write thread. + */ + + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <gri_ringbuffer.h> +#include <stdexcept> + + +/* Create a new ringbuffer to hold at least `sz' bytes of data. The + actual buffer size is rounded up to the next power of two. */ + +gri_ringbuffer::gri_ringbuffer (size_t sz) +{ + size_t power_of_two; + + for (power_of_two = 1; 1U << power_of_two < sz; power_of_two++); + + d_size = 1 << power_of_two; + d_size_mask = d_size; + d_size_mask -= 1; + d_write_ptr = 0; + d_read_ptr = 0; + d_buf = new char [d_size]; + + d_mlocked = 0; +} + +gri_ringbuffer::~gri_ringbuffer () +{ +#ifdef HAVE_SYS_MMAN_H + if (d_mlocked) { + munlock (d_buf, d_size); + } +#endif /* HAVE_SYS_MMAN_H */ + + delete [] d_buf; +} + +/* Lock the data block of ringbuffer using the system call 'mlock'. */ + +int +gri_ringbuffer::mlock (void) +{ +#ifdef HAVE_SYS_MMAN_H + if (::mlock (d_buf, d_size)) { + return -1; + } +#endif /* HAVE_SYS_MMAN_H */ + d_mlocked = 1; + return 0; +} + +/* Reset the read and write pointers to zero. This is not thread + safe. */ + +void +gri_ringbuffer::reset () +{ + d_read_ptr = 0; + d_write_ptr = 0; +} + +/* Return the number of bytes available for reading. This is the + number of bytes in front of the read pointer and behind the write + pointer. */ + +size_t +gri_ringbuffer::read_space () +{ + size_t w, r; + + w = d_write_ptr; + r = d_read_ptr; + + if (w > r) { + return w - r; + } else { + return (w - r + d_size) & d_size_mask; + } +} + +/* Return the number of bytes available for writing. This is the + number of bytes in front of the write pointer and behind the read + pointer. */ + +size_t +gri_ringbuffer::write_space () +{ + size_t w, r; + + w = d_write_ptr; + r = d_read_ptr; + + if (w > r) { + return ((r - w + d_size) & d_size_mask) - 1; + } else if (w < r) { + return (r - w) - 1; + } else { + return d_size - 1; + } +} + +/* The copying data reader. Copy at most `cnt' bytes from ringbuffer to + `dest'. Returns the actual number of bytes copied. */ + +size_t +gri_ringbuffer::read (char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + + if ((free_cnt = read_space ()) == 0) { + return 0; + } + + to_read = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = d_read_ptr + to_read; + + if (cnt2 > d_size) { + n1 = d_size - d_read_ptr; + n2 = cnt2 & d_size_mask; + } else { + n1 = to_read; + n2 = 0; + } + + memcpy (dest, &(d_buf[d_read_ptr]), n1); + d_read_ptr += n1; + d_read_ptr &= d_size_mask; + + if (n2) { + memcpy (dest + n1, &(d_buf[d_read_ptr]), n2); + d_read_ptr += n2; + d_read_ptr &= d_size_mask; + } + + return to_read; +} + +/* The copying data reader w/o read pointer advance. Copy at most + `cnt' bytes from ringbuffer to `dest'. Returns the actual number of bytes +copied. */ + +size_t +gri_ringbuffer::peek (char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + size_t tmp_read_ptr; + + tmp_read_ptr = d_read_ptr; + + if ((free_cnt = read_space ()) == 0) { + return 0; + } + + to_read = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = tmp_read_ptr + to_read; + + if (cnt2 > d_size) { + n1 = d_size - tmp_read_ptr; + n2 = cnt2 & d_size_mask; + } else { + n1 = to_read; + n2 = 0; + } + + memcpy (dest, &(d_buf[tmp_read_ptr]), n1); + tmp_read_ptr += n1; + tmp_read_ptr &= d_size_mask; + + if (n2) { + memcpy (dest + n1, &(d_buf[tmp_read_ptr]), n2); + tmp_read_ptr += n2; + tmp_read_ptr &= d_size_mask; + } + + return to_read; +} + + +/* The copying data writer. Copy at most `cnt' bytes to ringbuffer from + `src'. Returns the actual number of bytes copied. */ + +size_t +gri_ringbuffer::write (const char *src, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_write; + size_t n1, n2; + + if ((free_cnt = write_space ()) == 0) { + return 0; + } + + to_write = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = d_write_ptr + to_write; + + if (cnt2 > d_size) { + n1 = d_size - d_write_ptr; + n2 = cnt2 & d_size_mask; + } else { + n1 = to_write; + n2 = 0; + } + + memcpy (&(d_buf[d_write_ptr]), src, n1); + d_write_ptr += n1; + d_write_ptr &= d_size_mask; + + if (n2) { + memcpy (&(d_buf[d_write_ptr]), src + n1, n2); + d_write_ptr += n2; + d_write_ptr &= d_size_mask; + } + + return to_write; +} + +/* Advance the read pointer `cnt' places. */ + +void +gri_ringbuffer::read_advance (size_t cnt) +{ + d_read_ptr += cnt; + d_read_ptr &= d_size_mask; +} + +/* Advance the write pointer `cnt' places. */ + +void +gri_ringbuffer::write_advance (size_t cnt) +{ + d_write_ptr += cnt; + d_write_ptr &= d_size_mask; +} + +/* The non-copying data reader. `vec' is an array of two places. Set + the values at `vec' to hold the current readable data at ringbuffer. If + the readable data is in one segment the second segment has zero + length. */ + +void +gri_ringbuffer::get_read_vector (datavec_t * vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = d_write_ptr; + r = d_read_ptr; + + if (w > r) { + free_cnt = w - r; + } else { + free_cnt = (w - r + d_size) & d_size_mask; + } + + cnt2 = r + free_cnt; + + if (cnt2 > d_size) { + + /* Two part vector: the rest of the buffer after the current write + ptr, plus some from the start of the buffer. */ + + vec[0].buf = &(d_buf[r]); + vec[0].len = d_size - r; + vec[1].buf = d_buf; + vec[1].len = cnt2 & d_size_mask; + + } else { + + /* Single part vector: just the rest of the buffer */ + + vec[0].buf = &(d_buf[r]); + vec[0].len = free_cnt; + vec[1].len = 0; + } +} + +/* The non-copying data writer. `vec' is an array of two places. Set + the values at `vec' to hold the current writeable data at ringbuffer. If + the writeable data is in one segment the second segment has zero + length. */ + +void +gri_ringbuffer::get_write_vector (datavec_t * vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = d_write_ptr; + r = d_read_ptr; + + if (w > r) { + free_cnt = ((r - w + d_size) & d_size_mask) - 1; + } else if (w < r) { + free_cnt = (r - w) - 1; + } else { + free_cnt = d_size - 1; + } + + cnt2 = w + free_cnt; + + if (cnt2 > d_size) { + + /* Two part vector: the rest of the buffer after the current write + ptr, plus some from the start of the buffer. */ + + vec[0].buf = &(d_buf[w]); + vec[0].len = d_size - w; + vec[1].buf = d_buf; + vec[1].len = cnt2 & d_size_mask; + } else { + vec[0].buf = &(d_buf[w]); + vec[0].len = free_cnt; + vec[1].len = 0; + } +} +
Index: Makefile.in =================================================================== RCS file: /home/cvs/portaudio/Makefile.in,v retrieving revision 1.4.2.22 diff -u -b -B -w -p -r1.4.2.22 Makefile.in --- Makefile.in 9 Nov 2005 23:13:03 -0000 1.4.2.22 +++ Makefile.in 12 Mar 2006 20:51:18 -0000 @@ -139,13 +139,15 @@ lib/$(PADLLV): lib/ $(OBJS) Makefile $(P $(TESTS): bin/%: lib/$(PALIB) Makefile $(PAINC) pa_tests/%.c $(CC) -o $@ $(CFLAGS) pa_tests/$*.c lib/$(PALIB) $(LIBS) -install: lib/$(PALIB) lib/$(PADLLV) +install: lib/$(PALIB) lib/$(PADLLV) portaudio.pc $(INSTALL) -d $(PREFIX)/lib $(INSTALL) -m 644 lib/$(PADLLV) $(PREFIX)/lib/$(PADLLV) $(INSTALL) -m 644 lib/$(PALIB) $(PREFIX)/lib/$(PALIB) cd $(PREFIX)/lib && rm -f $(PADLL) && ln -s $(PADLLV) $(PADLL) $(INSTALL) -d $(PREFIX)/include $(INSTALL) -m 644 pa_common/portaudio.h $(PREFIX)/include/portaudio.h + $(INSTALL) -d $(PREFIX)/lib/pkgconfig + $(INSTALL) -m 644 portaudio.pc $(PREFIX)/lib/pkgconfig/portaudio.pc @echo "" @echo "------------------------------------------------------------" @echo "PortAudio was successfully installed." Index: configure.in =================================================================== RCS file: /home/cvs/portaudio/configure.in,v retrieving revision 1.4.2.25 diff -u -b -B -w -p -r1.4.2.25 configure.in --- configure.in 27 Feb 2006 15:05:04 -0000 1.4.2.25 +++ configure.in 12 Mar 2006 20:51:41 -0000 @@ -89,6 +89,7 @@ dnl extra variables AC_SUBST(OTHER_OBJS) AC_SUBST(PADLL) AC_SUBST(SHARED_FLAGS) +AC_SUBST(THREAD_CFLAGS) AC_SUBST(DLL_LIBS) AC_SUBST(CXXFLAGS) AC_SUBST(NASM) @@ -139,7 +140,8 @@ case "${host_os}" in OTHER_OBJS="pa_win_ds/pa_win_ds.o pa_win_ds/dsound_wrapper.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o"; LIBS="-lwinmm -lm -ldsound -lole32"; PADLL="portaudio.dll"; - SHARED_FLAGS="-shared -mthreads"; + THREAD_CFLAGS="-mthreads" + SHARED_FLAGS="-shared"; DLL_LIBS="-lwinmm -lm -L./dx7sdk/lib -ldsound -lole32"; #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\""; #CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO"; @@ -155,7 +157,8 @@ case "${host_os}" in OTHER_OBJS="pa_asio/pa_asio.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o pa_asio/iasiothiscallresolver.o $ASIODIR/common/asio.o $ASIODIR/host/asiodrivers.o $ASIODIR/host/pc/asiolist.o"; LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid"; PADLL="portaudio.dll"; - SHARED_FLAGS="-shared -mthreads"; + THREAD_CFLAGS="-mthreads" + SHARED_FLAGS="-shared"; DLL_LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid"; CFLAGS="$CFLAGS -ffast-math -fomit-frame-pointer -Ipa_common -Ipa_asio -I$ASIODIR/host/pc -I$ASIODIR/common -I$ASIODIR/host -DPA_NO_WMME -DPA_NO_DS -DPA_NO_WDMKS -DWINDOWS"; CXXFLAGS="$CFLAGS"; @@ -169,7 +172,8 @@ case "${host_os}" in OTHER_OBJS="pa_win_wdmks/pa_win_wdmks.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o"; LIBS="-lwinmm -lm -luuid -lsetupapi -lole32"; PADLL="portaudio.dll"; - SHARED_FLAGS="-shared -mthreads"; + THREAD_CFLAGS="-mthreads" + SHARED_FLAGS="-shared"; DLL_LIBS="-lwinmm -lm -L./dx7sdk/lib -luuid -lsetupapi -lole32"; #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\""; #CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO"; @@ -178,7 +182,8 @@ case "${host_os}" in OTHER_OBJS="pa_win_wmme/pa_win_wmme.o pa_win/pa_win_hostapis.o pa_win/pa_win_util.o"; LIBS="-lwinmm -lm -lstdc++ -lole32 -luuid"; PADLL="portaudio.dll"; - SHARED_FLAGS="-shared -mthreads"; + THREAD_CFLAGS="-mthreads" + SHARED_FLAGS="-shared"; DLL_LIBS="-lwinmm"; CFLAGS="$CFLAGS -Ipa_common -DPA_NO_DS -DPA_NO_ASIO -DPA_NO_WDMKS"; fi @@ -190,7 +195,8 @@ case "${host_os}" in OTHER_OBJS="pa_win_wmme/pa_win_wmme.o"; LIBS="-lwinmm -lm"; PADLL="portaudio.dll"; - SHARED_FLAGS="-shared -mthreads"; + THREAD_CFLAGS="-mthreads" + SHARED_FLAGS="-shared"; DLL_LIBS="-lwinmm"; ;; @@ -209,7 +215,7 @@ case "${host_os}" in dnl The _REENTRANT option for pthread safety. Perhaps not necessary but it 'll do no harm. dnl - CFLAGS="$CFLAGS -D_REENTRANT" + THREAD_CFLAGS="-D_REENTRANT" OTHER_OBJS="pa_sgi/pa_sgi.o pa_unix/pa_unix_hostapis.o pa_unix/pa_unix_util.o"; @@ -246,11 +252,13 @@ case "${host_os}" in OTHER_OBJS="$OTHER_OBJS pa_unix_oss/pa_unix_oss.o" AC_DEFINE(PA_USE_OSS) fi + THREAD_CFLAGS="-pthread" LIBS="$LIBS -lm -lpthread"; PADLL="libportaudio.so"; SHARED_FLAGS="-shared -fPIC"; OTHER_OBJS="$OTHER_OBJS pa_unix/pa_unix_hostapis.o pa_unix/pa_unix_util.o" esac +CFLAGS="$CFLAGS $THREAD_CFLAGS" -AC_OUTPUT([Makefile]) +AC_OUTPUT([Makefile portaudio.pc]) --- /dev/null 2006-03-10 00:02:48.821312048 +0100 +++ portaudio.pc.in 2006-03-11 14:49:17.000000000 +0100 @@ -0,0 +1,12 @@ [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ + +Name: portaudio +Description: Portable audio I/O +Requires: +Version: 19 + +Libs: -L${libdir} -lportaudio @LIBS@ +Cflags: -I${includedir} @THREAD_CFLAGS@
_______________________________________________ Discuss-gnuradio mailing list Discuss-gnuradio@gnu.org http://lists.gnu.org/mailman/listinfo/discuss-gnuradio