Ticket #69 (assigned enhancement)

Opened 2 years ago

Last modified 2 months ago

support airport express as audio sink

Reported by: funkyhat Assigned to: coling (accepted)
Priority: low Milestone:
Component: daemon Severity: normal
Keywords: Cc: jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec, nwinkler, daniel.silva@gmail.com, www@zulutango.org

Description

Using raop-play, (or Justeport?) it should be possible to find airport express audio devices on the network, and use it as an audio sink (hopefully with a method to release the device when there are no streams playing through it, so other computers running iTunes can use it without problems).

Is this a possibility? :-)

Change History

05/23/07 02:37:44 changed by lennart

  • priority changed from normal to low.
  • status changed from new to assigned.

I'd love to add this. But I don't have an airport, and due to cryptography it is impossible to implement a compatible RAOP server.

Feel free to donate me an airport express and I will be working on this. Promised!

08/26/07 04:24:47 changed by lennart

  • status changed from assigned to closed.
  • resolution set to wontfix.

11/17/07 09:18:56 changed by clee

Lennart, does your offer still stand?

Because if you're serious, I'll buy you an Airport Express and ship it to you as well as testing whatever code you write.

11/17/07 10:17:53 changed by jbglaw

Well, there would be another thingie I'd be interested in. For mpd, I once wrote the "generic_plugin", a plugin which calls an external program to decode any type of audio file. Something like that could be done as a pulseaudio module, too, but for output instead of input. (Maybe for input, too...)

It will add another extra latency, but I guess this would be a flexible packend for a lot of experimental uses. (Even for the input route, I can imagine some pretty neat usage patterns :-)

Do you think this would be worth to consider as a beginner's project to hack on Pulseaudio?

11/17/07 10:18:08 changed by jbglaw

  • cc set to jbglaw@lug-owl.de.

11/17/07 14:34:05 changed by jbglaw

Thinking about it... Shouldn't it be possible to use pacat with the monitor and stream the data to the airport? In that case, any sink will do.

01/09/08 13:07:30 changed by giray

Hi Guys ... Any progress on this?

01/27/08 20:13:27 changed by fjacquet

hi

do you have any news on this topic ? can I assist for tests ?

01/27/08 20:13:40 changed by fjacquet

  • status changed from closed to reopened.
  • resolution deleted.

03/27/08 16:15:19 changed by coling

My mate has just bought an Airport Express and I was able to play to it via the raop_play command line tool in about 10 seconds.

It should be relatively trivial to port the raop_play app to a pulse audio sink module. I think I'm gonna buy an older APE (they are relatively cheap now) and take a crack at implementing this in pulseaudio.

The server part is another thing altogether (which would allow iTunes users on windows and mac to play to a pulse server, or general purpose playing from windows or mac via AirFoil). But this would still be a huge boon for PA if it had this support. I'll keep you posted of my progress.

Col

03/27/08 16:15:29 changed by coling

  • cc changed from jbglaw@lug-owl.de to jbglaw@lug-owl.de, coling.

04/04/08 10:18:13 changed by coling

  • owner changed from lennart to coling.
  • status changed from reopened to new.

Just so people know, I'm working on this.

I've mostly finished the RTSP implementation in PA and will start work on the RAOP client part shortly... don't know when I'll get enough time to finish it off fully tho'.

04/28/08 13:20:57 changed by coling

  • status changed from new to assigned.

Just a little status update for those following this.

I've implemented some of the necessary "pulseified" bits from the raop_play utility, namely the rtsp client and the base64 stuff.

I've created a modified version of the raop_play utility which uses the pulseified versions as a test and it seems to be working properly.

I've also modified raop_play to use the openssl provided aes implementation which also seems to be successful in my tests.

The next stage now is to create the actual sink. I'm not sure when I'll get round to this but hopefully it wont take too long.

I'm doing this work in my own personal svn for the sake of my own sanity, but if Lennart wants to give me access to PA svn, I can do this in a public branch for further external feed back.

(follow-up: ↓ 15 ) 05/01/08 10:59:38 changed by giray

coling, any chance we can get sneek-peek and / or help you ...

(in reply to: ↑ 14 ) 05/01/08 11:13:34 changed by coling

Replying to giray:

coling, any chance we can get sneek-peek and / or help you ...

I can post some patches later if you like but I'll be very honest and say that (externally) it's nothing more than a modified raop_play so it's not something to wet your pants over just yet! :p

I'll need lots of testing when I finally get done. My SVN is on private server with no simple repo access to view directly. I'd be happy to do this publicly on Lennart's svn if I had access I've not actually asked him for that yet. Once this is done it will probably "prove" me as eligible ;)

05/05/08 13:40:09 changed by nwinkler

  • cc changed from jbglaw@lug-owl.de, coling to jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net.

05/07/08 03:35:06 changed by coling

OK, small progress update.

I'm working on this on in branches/coling/airport and there exists a hacked up raop_play in branches/coling/raop_play/pulseified. As the latter is just for verifying code, the relative paths are hard coded so it you're fiddling, you'll need the same folder layout as in svn.

What's working?

Well I have a fully asynchronous RTSP and RAOP client classes in pulse. A call back can be registered with the RAOP client which will be called whenever we want more audio data.

What still needs to be done?

Well all I need to do is wire up a sync and do the ALAC encoding, which is pretty simple stuff now :)

What needs to be done after that?

  • Move the header concatenation stuff over the pa_headerlist
  • Change the buffer in raop_client to be a memblock/memchunk/mempool.
  • Change the AES and RSA encryption stuff to use NSS rather than OpenSSL (due to licensing)
  • Better error handling/bail out on errors.
  • Autodetection and loading (in zeroconf discover).

And let's not forget...... when?

Well I don't know when I'll get this done but hopefully I'll have something worthy of testing within the next couple days, but failing that by next week.

05/11/08 14:27:27 changed by coling

OK guys. I've just committed a "working" sink :)

Now, it's really, really not ready for prime time yet and there's no point in reporting bugs (I see them too!), but it at least connects and lets you play some music :D

It only seems to work once. It also crashes the pulseaudio server quite often which I'll work on.

Still lots to do before it can be merged but it's at least something :)

05/19/08 00:11:21 changed by magicmonkey

Nice work - keep it going, get it working, and if it ends up as something I can install into Ubuntu then I'll be a very happy person :D

Quick note, though - the link above to branches/coling/airport should actually be to branches/coling/airtunes. Nothing major.

05/24/08 18:06:18 changed by felipec

  • cc changed from jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net to jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec.

(follow-up: ↓ 22 ) 05/24/08 20:36:42 changed by felipec

Is it possible to make this a standalone module?

(in reply to: ↑ 21 ) 05/24/08 22:43:31 changed by coling

Replying to felipec:

Is it possible to make this a standalone module?

What do you mean a "standalone module"? Do you mean sans pulseaudio daemon? If so, then no. I guess someone could make an alsa driver if they wanted.

There are already stand alone apps, see e.g. raop_play.

05/27/08 01:48:41 changed by coling

OK, this patch is now working pretty nicely, tho' still has a lot to do before it can be merged back to trunk:

  • Sort out endian swapping stuff.
  • Replace base64 with known LGPL compat version.
  • Replace openssl with libnss3
  • Migrate to glitch free
  • Solve latency issues

At the moment, if load this sink, it will connect and hog the specified airtunes device. Sadly there is a constant 8 second latency as I'm using simple tcp socket for flow control at present. Still quite usable for e.g. listening to music.

(follow-up: ↓ 25 ) 05/27/08 09:05:37 changed by nwinkler

  • cc changed from jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec to jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec, nwinkler.

Hi,

the raop-play project (http://sourceforge.net/projects/raop-play/) contains a working ALSA driver for this - I'm the current maintainer of this project. I'm very interested in seeing how the Pulseaudio sink is developing, sounds like a good thing.

BTW: The ALSA driver has the same 8 second lag - if you happen to fix this, I would like to apply the changes to the ALSA driver if you don't mind :-)

Best regards,

Nils

(in reply to: ↑ 24 ) 05/27/08 09:54:57 changed by coling

Replying to nwinkler:

the raop-play project (http://sourceforge.net/projects/raop-play/) contains a working ALSA driver for this - I'm the current maintainer of this project. I'm very interested in seeing how the Pulseaudio sink is developing, sounds like a good thing. BTW: The ALSA driver has the same 8 second lag - if you happen to fix this, I would like to apply the changes to the ALSA driver if you don't mind :-)

Nice! I wasn't actually aware that raop_play had an alsa driver component. Teaches me for not poking around properly in the archive!

I'll certainly let you know about the 8 second lag. The most obvious solution is to not use tcp flow control for the buffer filling process and instead use a real time loop to fill up the data. This means the buffer on the airtunes is never totally full.

I did use some of raop play here for inspiration but the PA compnent here is a full rewrite based around PA's async core, so there is no blocking or sleeping anywhere. I do have a hacked up version of raop play (that is really ugly in terms of it's main loop) that does mostly work with this new async stuff. Feel free to poke around with it if you like, but not sure if it's of any benefit to you!

Col

(follow-up: ↓ 27 ) 06/10/08 10:08:59 changed by cdemoulins

I would like to test your module (module-raop-sink). I compile checkout your branche and compile is ok but how can i load your module ? I test add the line "load-module module-raop-sink" but i have errors. Can your help me ?

(in reply to: ↑ 26 ) 06/10/08 10:13:31 changed by coling

Replying to cdemoulins:

I would like to test your module (module-raop-sink). I compile checkout your branche and compile is ok but how can i load your module ? I test add the line "load-module module-raop-sink" but i have errors. Can your help me ?

Sure. You have to pass server=<IPADDR> argument when you load the module.

I usually start pulseaudio -vvv in a terminal then issue a separate pactl load-module module-raop-sink sink_name=airtunes server=<IP ADDR> command.

Hope that helps.

06/10/08 10:15:08 changed by coling

Incidentally, to follow up on my last comment, I fully intend to support autodiscovery but this will be done as a separate module (much like how module-zeroconf-discover and module-tunnel-sink work). It may just be an ifdef'ed modification of module-zeroconf-discover - I've not really gotten to that part of the design yet as there are more fundamental things to look at first :D

06/10/08 16:00:07 changed by cdemoulins

It works, thanks.

06/11/08 01:55:59 changed by coling

(In [2503]) Add some new public API functions to connect and flush. This allows us to reconnect upon disconnection but this has thus far proved unreliable. We no longer close the socket. We leave this to the module thread to do the closing. We can also flush the remote buffer now. Refs #69

06/11/08 02:02:17 changed by coling

(In [2504]) Still send silence when we are not doing anything else, but also flush the buffers correctly upon recovery from suspension. Close the RTP socket correctly after passing messages about. When not sending silence, the RTSP socket will be closed after some period of inactivity. I'm not sure why this is. Sending silence keeps things working and with the flushes after suspension we now get a better latency. As this relies on the auto-suspend feature, it's not exactly ideal. Typical latencies are currently about 3s which makes it more or less usuable for listening to music. If the connection is disconnected, it will reconnect but I've found that the second connection is silent. Hopefully the silence will prevent the first connection dropping. Refs #69

06/11/08 18:28:02 changed by Cabalist

I'd also like to say Thanks! :)

06/12/08 00:44:10 changed by coling

(In [2519]) Automatic discovery of airtunes devices via Bonjour/Avahi. This also does some minor reordering in the Makefile.am Refs #69

06/14/08 19:04:46 changed by dsilva

  • cc changed from jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec, nwinkler to jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec, nwinkler, daniel.silva@gmail.com.

06/17/08 18:08:16 changed by tsibley

  • cc changed from jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec, nwinkler, daniel.silva@gmail.com to jbglaw@lug-owl.de, coling, nwinkler@users.sourceforge.net, felipec, nwinkler, daniel.silva@gmail.com, www@zulutango.org.

(follow-up: ↓ 37 ) 06/17/08 18:09:19 changed by tsibley

Thank you for this work, it sounds really promising! Any ideas on completion / usability?

(in reply to: ↑ 36 ; follow-up: ↓ 38 ) 06/17/08 19:21:35 changed by coling

Replying to tsibley:

Thank you for this work, it sounds really promising! Any ideas on completion / usability?

Well there are a few show stoppers before official shipping can be done. I'm not really confident I'll have the time to get that done before 0.9.11 ships but then I'm not really sure when that's supposed to be either! I'm guessing "fairly soon" is the best estimate we'll get!

The main things I need to do before it can be shipped is get rid of the dependency on OpenSSL. I need to convert to GNU TLS or NSS3 for licensing reasons.

Other than that it's in fairly good shape - still plenty to do but more than usable for audio (crap for video!).

It currently hogs the airport device and sends silence over the network all the time. which is far from ideal, but all other methods had issues after the first connection (second connection would simply not work - appears to in theory but no sound... it's really odd and has caused much banging of head against wall so far!)

(in reply to: ↑ 37 ) 06/18/08 02:29:13 changed by tsibley

Replying to coling:

Other than that it's in fairly good shape - still plenty to do but more than usable for audio (crap for video!).

Great! Is there a ~relatively easy way to build the module and then use it with an unmodified pulseaudio 0.9.10? Will building your branch and just copying the module into the right place work? It'd like to test it out. :)

(follow-up: ↓ 53 ) 06/18/08 11:09:58 changed by coling

Actually, I have to take back the "working fairly well" comment. I ran into issue last night when I actually tried to use it (as opposed ot just develop it). Something to do with memory pools and allocating too much. I'll need to look into it :)

As for building, it's not really a simple job sadly. It does touch on a couple of other files so the module on it's own is not actually sufficient... (librtp.so will defo be needed as will (IIRC) libpulsecore.so but generally I wouldn't recommend it).

Personally, I have my system pulse installed and I've just done the following to install this at the same time. I've not tested this since the git migration so apologies if this doesn't work 100%. I'll also be setting up some personal git repos for this in due course and continuing development on that (this is standard git workflow). I'll let you know when that's done.

git clone git://git.0pointer.de/pulseaudio
cd pulseaudio
git checkout origin/coling
cd airtunes
./bootstrap.sh --prefix /usr/local/pulse/ (or any folder of your choice)
make
sudo make install
cd /usr/local/pulse/bin/
./pulseaudio -k
./pulseaudio -vvv

< other terminal >
pactl load-module module-raop-discover

That should do it, but like I say I've had some issues using it practically (moving streams via pavucontrol + amarok2), but setting PULSE_SINK and running mplayer on command line has been OK.

Hope this helps.

06/22/08 15:30:39 changed by ildella

I cannot go beyond the ./bootstrap command:

+ aclocal aclocal: configure.ac: 423: macro `AM_ICONV' not found in library

I am using ubuntu 8.04 and I have installed some libraries to arrive to this blocking point.

Here is the complete output. With automake 1.9 it goes further but eventually fails for the same issue.

della@della-laptop:~/workspace/pulseaudio/airtunes$ ./bootstrap.sh --prefix /usr/local/pulse/ + ' x--prefix = xam ?' + rm -rf autom4te.cache + rm -f config.cache + touch config.rpath + test x = x + LIBTOOLIZE=libtoolize + libtoolize -c --force --ltdl + run_versioned aclocal 1.10 + local P + local V ++ echo 1.10 ++ sed -e 's,\.g' + V=110 ++ which aclocal110 + '[' -e ']' ++ which aclocal-1.10 + '[' -e ']' + P=aclocal + shift 2 + aclocal aclocal: configure.ac: 423: macro `AM_ICONV' not found in library

06/22/08 15:31:39 changed by ildella

here is the output formatted:

+ '[' x--prefix = xam ']'
+ rm -rf autom4te.cache
+ rm -f config.cache
+ touch config.rpath
+ test x = x
+ LIBTOOLIZE=libtoolize
+ libtoolize -c --force --ltdl
+ run_versioned aclocal 1.10
+ local P
+ local V
++ echo 1.10
++ sed -e 's,\.,,g'
+ V=110
++ which aclocal110
+ '[' -e '' ']'
++ which aclocal-1.10
+ '[' -e '' ']'
+ P=aclocal
+ shift 2
+ aclocal
aclocal: configure.ac: 423: macro `AM_ICONV' not found in library

06/22/08 18:31:33 changed by coling

Hi ildella. The problems you are having are not specific to this branch and this topic so it would be better if you asked this kind of stuff on the mailing list rather than here. In this case I'd guess you don't have the iconv development package installed. I don't use Ubuntu so I don't know which package you need to install. Feel free to pop in to the IRC channel and someone will probably help you out :)

(follow-up: ↓ 44 ) 06/24/08 17:12:09 changed by cdemoulins

It's great with the discover :) The last problem for me is the latency, when i change sound level i have to wait 7-8 sec.

(in reply to: ↑ 43 ) 06/24/08 17:23:03 changed by coling

Replying to cdemoulins:

It's great with the discover :) The last problem for me is the latency, when i change sound level i have to wait 7-8 sec.

Yup, that should be easy enough to support as the device has hardware volume support... that said it wont help in setting stream volume..... Ideally I want to solve the whole latency issue completely but that will require some more indepth tweaks and I'm running a bit low on time at the moment :s

I will announce a new (temporary - i.e. until it's merged) home for the module shortly... I'm just tweaking my own personal git repository and I'm still hacking around with branches to keep the git history in tact (and learning git properly in the process which is fun but means breakages!!)

06/28/08 12:23:42 changed by felipec

This is with 92a4467e0caa89e42a74d40bc15d1ee60c733054.

I: client.c: Created 1 "Native client (UNIX socket client)" I: protocol-native.c: Got credentials: uid=500 gid=500 success=1 I: protocol-native.c: Enabled SHM for new connection I: client.c: Client 1 changed name from "Native client (UNIX socket client)" to "pactl" E: module.c: Failed to open module "module-raop-discover": module-raop-discover.so: cannot open shared object file: No such file or directory I: client.c: Freed 1 "pactl" I: protocol-native.c: connection died.

06/28/08 12:44:51 changed by felipec

Ah, nevermind, I was missing avahi-devel.

06/28/08 13:17:47 changed by felipec

All right it works :)

However, it sounds very bad. I hear 3 seconds of sound, then 10 of silence, and again.

D: rtsp_client.c: Sending command: FLUSH
D: module-suspend-on-idle.c: Sink airtunes.7-Seas.local becomes idle.
D: module-suspend-on-idle.c: Sink airtunes.7-Seas.local becomes busy.
I: resampler.c: Forcing resampler 'copy', because of fixed, identical sample rates.
I: resampler.c: Using resampler 'copy'
I: resampler.c: Using float32le as working format.
I: sink-input.c: Created input 8 "foo.wav" on airtunes.7-Seas.local with sample spec float32le 2ch 44100Hz and channel map front-left,front-right
D: memblock.c: Memory block too large for pool: 17640 > 16376
D: memblockq.c: memblockq requested: maxlength=264600, tlength=176400, base=8, prebuf=172872, minreq=3528
D: memblockq.c: memblockq sanitized: maxlength=264600, tlength=176400, base=8, prebuf=172872, minreq=3528
D: rtsp_client.c: Full response received. Dispatching
D: raop_client.c: RAOP: FLUSHED

06/29/08 12:33:38 changed by coling

felipec: Yeah I see those problems too. Funny thing is, doing PULSE_SINK=blah mplayer file seems to work pretty well, but moving a stream in pavucontrol goes all crazy like above. I'll work out what I need to do to fix it up in due course :)

Just to update everyone, you can now get the code from here (nothing significant has been done there since migrating from SVN... yet!!): http://colin.guthr.ie/git/pulseaudio/

06/29/08 13:48:36 changed by felipec

I tried PULSE_SINK=airtunes.foo.local mplayer -ao pulse file and still doesn't play smoothly.

However, I think this should be merged into the master branch anyway :)

07/04/08 00:58:22 changed by coling

I sat down to try and fix choppy playback but for some reason, things played very smoothly for me. mplayer -ao pulse is my test platform (xine seems to have issues right now - after running it, it breaks the sink for all other uses, even mplayer :s). I'll debug more later.

I have however, implemented volume support. This allows for near instantaneous adjustment of the volume of the output device. Stream volume changes still take a while to filter through as expected. I'll try and work on some kind of real time data feed at some point to address this delay.

07/04/08 00:59:56 changed by coling

Oh, just so those following this are clear: please see comment:48 for the correct git repository.

07/08/08 14:57:05 changed by felipec

After your volume changes now everything works great :)

Thanks a lot!

(in reply to: ↑ 39 ; follow-up: ↓ 54 ) 07/10/08 18:13:57 changed by johnc32779

  • type changed from enhancement to defect.

Replying to coling:

Personally, I have my system pulse installed and I've just done the following to install this at the same time. I've not tested this since the git migration so apologies if this doesn't work 100%. I'll also be setting up some personal git repos for this in due course and continuing development on that (this is standard git workflow). I'll let you know when that's done. {{{ git clone git://git.0pointer.de/pulseaudio cd pulseaudio git checkout origin/coling cd airtunes ./bootstrap.sh --prefix /usr/local/pulse/ (or any folder of your choice) make sudo make install cd /usr/local/pulse/bin/ ./pulseaudio -k ./pulseaudio -vvv < other terminal > pactl load-module module-raop-discover }}}

Followed the above procedure and everything went swell without error except for the last line "pactl load-module module-raop-discover". Seems module-raop-discover was not built and installed.

(in reply to: ↑ 53 ) 07/10/08 23:39:43 changed by coling

Replying to johnc32779:

Followed the above procedure and everything went swell without error except for the last line "pactl load-module module-raop-discover". Seems module-raop-discover was not built and installed.

Yeah the -discover module was added after I migrated to my own git repo IIRC.

The updated details as noted in comment:48 and comment:51 are:

git clone git://colin.guthr.ie/pulseaudio
cd pulseaudio
git checkout origin/airtunes-0.9.10

07/11/08 19:40:56 changed by johnc32779

  • type changed from defect to enhancement.

Thank you Coling -- module-raop-discover now loads and indeed discovers both of my airport express units. Now I need to learn how to drive this thing.

07/12/08 18:08:02 changed by johnc32779

Using paplay my wav files play perfectly. "manager" under "padevchooser" displays correct information. However I get no sound output under tab Sample Cache with airtunes selected when play is depressed.

08/22/08 11:06:33 changed by ildella

Hi all.

Any news after the summer ? :)

08/22/08 13:59:38 changed by coling

Not a lot of news. It works, but not perfectly :) I need to find time to work on it a bit more. Lennart will probably pull it in to master sometime in the next couple of weeks for inclusion in PA 0.9.12 but hopefully I'll get time to tidy up the timing code before it goes final.