Gr-audio OSX fixes test branch

I just pushed the latest WIP for fixing gr-audio on OSX; I hope some
adventurous OSX users can test this branch out & provide feedback! If
you want to help, but don’t know how, ask me and I’ll provide
instructions. - MLD

< https://github.com/michaelld/gnuradio/tree/fix_gr_audio_osx >

Fixes that I’ve tested and seem to work for me:

  • device selection via command line/instantiation arguments (e.g.,
    “dial_tone -O foo” or “audio_fft -I bar”);
  • device selection by full or partial name, case sensitive (for now;
    e.g., “audio_fft -O FUN” to get the “FUNcube Dongle” device);
  • correct sample rate detection and use for non-Apple provided audio
    devices (e.g., FUNcube Dongle).

Fix that I have not yet tested but should work:

  • flow-graph start/stop.

Fixes that I’m still working on:

  • if the default audio device is used (meaning, no audio device name is
    specified at instantiation), then track when the user changes the
    default audio device and switch to using it;
  • if a removable device is selected (default or directly), then track if
    the device is removed and switch to another device.

I’m happy to test it for you Michael.
Want to give me a scenario?


View this message in context:
http://gnuradio.4.n7.nabble.com/gr-audio-OSX-fixes-test-branch-tp46465p46503.html
Sent from the GnuRadio mailing list archive at Nabble.com.

Another update to <
https://github.com/michaelld/gnuradio/tree/fix_gr_audio_osx >:

  • the audio source should be working fully now; I’ve tested with both
    the built-in mic and a FUNcube Dongle Pro (not Pro+) and device
    selection works and sample rates are correct;

  • audio source devices can be added and removed, and the source device
    usage will be reconfigured on the fly (sink does not work like this yet;
    hopefully tomorrow …);

  • fixes a bug making low sample rates usable again (source and sink);

  • should not have any multi-threading conflicts (source; sink does not
    have these yet);

  • can use the “Default Audio Device” and switch it using System
    Preferences on the fly (source only right now; sink hopefully tomorrow
    …).

Now that the source works with all this “on the fly” stuff, it’ll be
simple to move that over to the sink – of course, I do not have
multiple audio sinks from which to choose so I’ll make those changes,
push them, and hope someone else can test them for functionality. Since
the sink and source codes will be roughly equivalent in threading /
protection, they should both work the same for “in the fly” stuff.

If you want do use MacPorts to test out these changes, here’s what I
recommend you do:

  1. make sure the gnuradio-devel port is installed and up to date
    {{{
    sudo port -f deactivate port installed | grep gnuradio | sed -e "s@(active)@@g"
    sudo port install gnuradio-devel
    sudo port selfupdate
    sudo port upgrade gnuradio-devel
    }}}

  2. Download the patch for these fixes; you can get them via my github
    branch above (commit eaf27b15b4), and I’ve also put them into DropBox:
    <
    https://dl.dropboxusercontent.com/u/16655336/gr-audio-osx-wip-2014-02-25.diff

  1. Patch gnuradio-devel; change “/PATH/TO” to be the correct path to the
    patch:
    {{{
    sudo port patch gnuradio-devel
    cd port work gnuradio-devel/gnuradio*
    sudo patch -p1 < /PATH/TO/gr-audio-osx-wip-2014-02-25.diff
    }}}

  2. build gnuradio-devel:
    {{{
    sudo port build gnuradio-devel
    }}}

  3. install the gr audio library (assuming PREFIX=/opt/local; if not,
    change the “cp” destination):
    {{{
    cd port work gnuradio-devel/build/gr-audio/lib
    sudo cp libgnuradio-audio.3.7.3git.dylib /opt/local/lib
    }}}

  4. Try it out! For example:
    {{{
    /opt/local/share/gnuradio/examples/audio/audio_fft.py -r 96000 -I FUN
    /opt/local/share/gnuradio/examples/audio/dial_tone.py -r 1200 -O Built
    }}}

Try different rates, and different I/O devices. You should see
printouts from “audio_osx_source” and “audio_osx_sink” with information
about what it’s doing.

Let me know what you think! - MLD

Hi Kevin - Thanks for the feedback and related info; it’s nice to hear
from another GR on OSX user! I’ll push changes to the sink either today
or tomorrow for testing. - MLD

On Feb 26, 2014, at 12:33 AM, Kevin R. [email protected] wrote:

For the audio source, flowgraph start/stop/reconfiguring and specifying the
device name both work fine as far as I’ve tested them.

Good! I’m glad you were able to test these out. Just because they work
for me does not mean they work for everyone :slight_smile:

  1. … or (fewer harmless errors, same effect)
    sudo port -f deactivate installed and ‘gnuradio*’

Haha! Even as a MacPorts developer I cannot keep up with “port” CLI
usage. I love “sudo port -f deactivate installed and ‘gnuradio*’” –
that’s so concise yet robust. Thanks for the info; now, I have to play
with these to see what it can do!

  1. Mucking with MacPorts prefix files manually is a bad practice; why not just
    install the gnuradio built in step 4? (Worked for me – ‘sudo port install -s
    gnuradio’) Doing this also means you only need to build/install gnuradio-devel
    once (rather than installing it before patching it).

I intentionally had the user install gnuradio-devel then create a
patched version in case things got messed up, for 2 reasons [I should have written these into the original email.]:

a) If things get messed up either building or after copying
libgnuradio-audio, you can clean it up by doing
{{{
sudo port -f deactivate gnuradio-devel
sudo port activate gnuradio-devel
}}}
and start from go.

b) Sometimes ‘port’ thinks it is being smart by looking at the available
(deactivated) versions of a port, comparing to what is being requested,
and then activating a port instead of finishing the install of what you
already have being compiled. Adding in the “-s” (from source) does not
always help. Hence, having the user copy the library by hand – it’s
not difficult, and it’s easy to clean up if things don’t work right.

I hope that the final version will not send text to stdout, because this
interferes with a program delivering data to stdout; preferably all log-ish output
should be optional (other components of gnuradio fail at this), and if present it
should go to stderr rather than stdout.

I can move these printouts to stderr, even though they are not errors;
some are warnings and some just informational. What do others think:
stdout or stderr?

The behavior on not finding the specified device should not be using the default
device; instead, it should fail in a way the caller can observe. Doing otherwise
creates or hides bugs. (For example, suppose I’m building a publicly accessible
receiver (like WebSDR) using a soundcard interface; if it used the default input
device if that device wasn’t found, there’s a good chance I’d then be streaming
audio from the room the computer is in, which is a privacy problem!)

Right now, if the specified device (from, e.g., -I or -O) is not found,
then it reverts back to the default device. What you’re asking for is
for it to instead fail and print out some stuff to stderr, yes? That’s
certainly an option. I’d value other’s opinions on this matter.

Furthermore any information important enough to warn on ought to be exposed to
the caller, not just stderr/stdout, if nothing else so that non-console-based
applications can communicate the information to their actual user interface, as
well as performing appropriate error handling.

I don’t think GNU Radio supports this sort of caller exposure. I think
it can provide “log to file” and “print to terminal”, but not
communication with non-console-based applications – as a general rule.
If/when we move completely over to using Qt instead of Wx, then maybe
this can be an option; until then, we need to stick with those 2
options. That said, I’m open to listening to what others have to say on
this matter.

On Feb 25, 2014, at 19:06, Michael D. [email protected]
wrote:

Another update to < https://github.com/michaelld/gnuradio/tree/fix_gr_audio_osx
:

If you want do use MacPorts to test out these changes, here’s what I recommend
you do:

Thanks for including the instructions; otherwise I probably wouldn’t
have gotten around to testing (as I haven’t before).

  1. make sure the gnuradio-devel port is installed and up to date
    {{{
    sudo port -f deactivate port installed | grep gnuradio | sed -e "s@(active)@@g"

This can be more robustly written as

sudo port -f deactivate 'gnuradio*'

or (fewer harmless errors, same effect)

sudo port -f deactivate installed and 'gnuradio*'
  1. install the gr audio library (assuming PREFIX=/opt/local; if not, change the
    “cp” destination):
    {{{
    cd port work gnuradio-devel/build/gr-audio/lib
    sudo cp libgnuradio-audio.3.7.3git.dylib /opt/local/lib
    }}}

Mucking with MacPorts prefix files manually is a bad practice; why not
just install the gnuradio built in step 4? (Worked for me – ‘sudo port
install -s gnuradio’) Doing this also means you only need to
build/install gnuradio-devel once (rather than installing it before
patching it).

Try different rates, and different I/O devices. You should see printouts from
“audio_osx_source” and “audio_osx_sink” with information about what it’s doing.

Let me know what you think! - MLD

For the audio source, flowgraph start/stop/reconfiguring and specifying
the device name both work fine as far as I’ve tested them.

Some criticism of incidental aspects:

I hope that the final version will not send text to stdout, because this
interferes with a program delivering data to stdout; preferably all
log-ish output should be optional (other components of gnuradio fail at
this), and if present it should go to stderr rather than stdout.

The behavior on not finding the specified device should not be using the
default device; instead, it should fail in a way the caller can observe.
Doing otherwise creates or hides bugs. (For example, suppose I’m
building a publicly accessible receiver (like WebSDR) using a soundcard
interface; if it used the default input device if that device wasn’t
found, there’s a good chance I’d then be streaming audio from the room
the computer is in, which is a privacy problem!)

Furthermore any information important enough to warn on ought to be
exposed to the caller, not just stderr/stdout, if nothing else so that
non-console-based applications can communicate the information to their
actual user interface, as well as performing appropriate error handling.


Kevin R. http://switchb.org/kpreid/

On Wed, Feb 26, 2014 at 7:57 AM, Michael D.
[email protected] wrote:

Haha! Even as a MacPorts developer I cannot keep up with “port” CLI usage. I
love “sudo port -f deactivate installed and ‘gnuradio*’” – that’s so concise yet
robust. Thanks for the info; now, I have to play with these to see what it can
do!
and start from go.

b) Sometimes ‘port’ thinks it is being smart by looking at the available
(deactivated) versions of a port, comparing to what is being requested, and then
activating a port instead of finishing the install of what you already have being
compiled. Adding in the “-s” (from source) does not always help. Hence, having
the user copy the library by hand – it’s not difficult, and it’s easy to clean up
if things don’t work right.

I hope that the final version will not send text to stdout, because this
interferes with a program delivering data to stdout; preferably all log-ish output
should be optional (other components of gnuradio fail at this), and if present it
should go to stderr rather than stdout.

I can move these printouts to stderr, even though they are not errors; some are
warnings and some just informational. What do others think: stdout or stderr?

We now have the logging interface in GNU Radio to handle these cases.
I can work off-line with Michael to use this properly. In a gr::block
derived class, it’s very simple since a d_logger object already exists
for them. Otherwise, there’s some setup that’s required.

The behavior on not finding the specified device should not be using the
default device; instead, it should fail in a way the caller can observe. Doing
otherwise creates or hides bugs. (For example, suppose I’m building a publicly
accessible receiver (like WebSDR) using a soundcard interface; if it used the
default input device if that device wasn’t found, there’s a good chance I’d then
be streaming audio from the room the computer is in, which is a privacy problem!)

Right now, if the specified device (from, e.g., -I or -O) is not found, then it
reverts back to the default device. What you’re asking for is for it to instead
fail and print out some stuff to stderr, yes? That’s certainly an option. I’d
value other’s opinions on this matter.

Typically, the way we handle failures is to fail and exit and not make
assumptions about what the next best option is (this is probably not
universally true within our code, but it’s how we try and treat these
situations).

Furthermore any information important enough to warn on ought to be exposed to
the caller, not just stderr/stdout, if nothing else so that non-console-based
applications can communicate the information to their actual user interface, as
well as performing appropriate error handling.

I don’t think GNU Radio supports this sort of caller exposure. I think it can
provide “log to file” and “print to terminal”, but not communication with
non-console-based applications – as a general rule. If/when we move completely
over to using Qt instead of Wx, then maybe this can be an option; until then, we
need to stick with those 2 options. That said, I’m open to listening to what
others have to say on this matter.

Again, we’d use the logger for these things. We inherit from log4cpp
and can configure our logger to use whatever features we get from that
project.

Tom

On Feb 26, 2014, at 4:57, Michael D. [email protected]
wrote:

The behavior on not finding the specified device should not be using the
default device; instead, it should fail in a way the caller can observe. Doing
otherwise creates or hides bugs. (For example, suppose I’m building a publicly
accessible receiver (like WebSDR) using a soundcard interface; if it used the
default input device if that device wasn’t found, there’s a good chance I’d then
be streaming audio from the room the computer is in, which is a privacy problem!)

Right now, if the specified device (from, e.g., -I or -O) is not found, then it
reverts back to the default device. What you’re asking for is for it to instead
fail and print out some stuff to stderr, yes?

No, if it’s going to fail in a way the caller can detect and handle,
then printing is irrelevant and undesirable (unmodular).

GNU Radio is a library as well as a framework. As a library, it should
(ideally) permit complete control over its inputs and outputs by the
code which invokes it.

I see Tom R. wrote that current GR has a logging facility; that’s
an appropriate thing to use here (if the logging can’t be redirected or
suppressed, then that’s no longer your problem).

Furthermore any information important enough to warn on ought to be exposed to
the caller, not just stderr/stdout, if nothing else so that non-console-based
applications can communicate the information to their actual user interface, as
well as performing appropriate error handling.

I don’t think GNU Radio supports this sort of caller exposure. I think it can
provide “log to file” and “print to terminal”, but not communication with
non-console-based applications – as a general rule.

I think I’ve managed to confuse the issue by combining discussion of
printing with discussion of error handling. I do NOT want GNU
Radio to go putting up GUI dialogs or anything like that – in my
particular use case (the GR process is also a web server) that would by
equally or more useless than printing to console. What matters is that
the caller is able to perform error handling.

As a user of GNU Radio from Python, this is what I want to write:

try:
self.source = gnuradio.audio.source(device_name=‘foo’)
except KeyError: # or whatever fits ‘device not found’
# do application-specific error handling

This is preferable, but I get the impression that failing in block
constructors is problematic, based on comments in gr-osmosdr; it would
also be acceptable if there’s a way to find out afterward (gr-osmosdr
provides one sort of accidentally):

self.source = gnuradio.audio.source(device_name=‘foo’)
if not self.source.get_valid():
# do application-specific error handling

This would also allow you to provide fallback behavior such as a source
of 0s at the requested sample rate, which might be a desirable default
in some applications (e.g. a transceiver with no microphone device falls
back to being a receiver).

Both of these are examples of exposing success/failure to the caller of
the constructor
which can then handle it in an appropriate way. This is
the only thing that I am arguing is critical. Whether logging occurs in
addition to this is a separate issue.

(Note that there are also, of course, non-OSX audio sinks/sources; I
don’t know how they signal failure to the caller but it should be made
the same on all platforms. If there’s an existing failure-signaling path
for non-OSX then we should just use that everywhere.)


Kevin R. http://switchb.org/kpreid/

Hi Michael,

Following your step by step guide, I could successfully test your
changes with the Funcube Dongle Pro+ and a few USB audio devices. I
tested using audio_fft.py and dial_tone.py. It really works great;
it’s amazing when one can use almost random sample rates and the audio
system will take care of everything :slight_smile:

I hope your patch can be committed very soon. Even if there are some
bugs left, it works far better than the current code.

Alex

On Sat, Mar 1, 2014 at 11:05 PM, Michael D.

I just pushed the latest, and, maybe, final, changes to my gr-audio OSX
test branch:
< https://github.com/michaelld/gnuradio/tree/fix_gr_audio_osx >

The latest changes move the osx_impl functions into gr::audio::osx, use
them correctly, and install the osx_impl.h header (with the other audio
headers) but iff OSX audio is enabled. If OSX audio is not enabled,
then this header will not be installed (but the other audio headers
still will be) and gr::audio:osx will not exist or be populated. It is
up to the using project to verify that <gnuradio/audio/osx_impl.h>
exists …

Patch file is at <
https://dl.dropboxusercontent.com/u/16655336/gr-audio-osx-wip-2014-03-05.diff

for those wanting to try it out with directions from prior emails. -
MLD

I just pushed the latest changes to my gr-audio OSX test branch:
< https://github.com/michaelld/gnuradio/tree/fix_gr_audio_osx >

fix gr-audio osx:

  • use GNU Radio preferences file to set default input and output audio
    device, if provided;
  • use gr::logger for all non-debug messages;
  • case-insensitive string find with desired audio device name;
  • fixes buffer allocation bug with low sample rates;
  • allows using a specific (named) audio device, or the default;
  • handles the case when the selected audio device becomes unavailable
    (e.g., a USB stick is removed while in use);
  • if no audio device name is provided, uses the default audio device as
    found in System Preferences::Sound;
  • handles the case when the default audio device is in use, and the user
    changes that audio device in System Preferences::Sound, by internally
    resetting to use the newly selected audio device;
  • all non-Apple names are now lower_case, not CamelCase.

I believe the behavior is now as discussed by Kevin, Tom, myself, and
others. And, at least for me, everything works as desired on OSX 10.8.
These changes should work back to at least OSX 10.4, maybe even earlier.

If you want do use MacPorts to test out these changes, here’s what I
recommend you do:

  1. make sure the gnuradio-devel port is installed and up to date
    {{{
    sudo port -f deactivate installed and “gnuradio*”
    sudo port install gnuradio-devel
    sudo port selfupdate
    sudo port upgrade gnuradio-devel
    }}}

  2. Download the patch for these fixes; you can get them via my github
    branch above (commit 55eaa7da48), and I’ve also put them into my public
    DropBox folder:
    <
    https://dl.dropboxusercontent.com/u/16655336/gr-audio-osx-wip-2014-03-01.diff

  1. Patch gnuradio-devel; change “/PATH/TO” to be the correct path to the
    patch:
    {{{
    sudo port patch gnuradio-devel
    cd port work gnuradio-devel/gnuradio*
    sudo patch -p1 < /PATH/TO/gr-audio-osx-wip-2014-03-01.diff
    }}}

  2. build gnuradio-devel:
    {{{
    sudo port build gnuradio-devel
    }}}

  3. install the new gr audio library (assuming PREFIX=/opt/local; if not,
    change the “cp” destination):
    {{{
    cd port work gnuradio-devel/build/gr-audio/lib
    sudo cp libgnuradio-audio.3.7.3git.dylib /opt/local/lib
    }}}

  4. Try it out! For example:
    {{{
    /opt/local/share/gnuradio/examples/audio/audio_fft.py -r 96000 -I FUN
    /opt/local/share/gnuradio/examples/audio/dial_tone.py -r 1200 -O BuIlT
    }}}

Try different rates, and different I/O devices. You should see LOG
printouts from “audio_osx_source” and “audio_osx_sink” with information
about what it’s doing.

Let me know what you think! - MLD

ps> I intentionally am having you install gnuradio-devel then create a
patched version in case things got messed up, for 2 reasons:

a) If things get messed up either building or after copying
libgnuradio-audio, you can clean it up by doing
{{{
sudo port -f deactivate gnuradio-devel
sudo port activate gnuradio-devel
}}}
and start from go.

b) Sometimes ‘port’ thinks it is being smart by looking at the available
(deactivated) versions of a port, comparing to what is being requested,
and then activating a port instead of finishing the install of what you
already have being compiled. Adding in the “-s” (from source) does not
always help. Hence, my having you copy the library by hand – it’s not
difficult, and it’s easy to clean up if things don’t work right.


Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio