GNOME Bugzilla – Bug 542510
[apexsink] Apple AirPort Express Wireless Sink
Last modified: 2011-01-06 07:30:56 UTC
Sink definition : stream raw input sound to an Apple AirPort Express (simple ALAC encapsulation, RAOP control definition, data AES RSA encryption).
Created attachment 114385 [details] APEX sink plugin sources
Just some random notes, I'll take a closer look tomorrow: - Could you attach it as a diff to gst-plugins-bad, including build system modifications? - Why exactly is the openssl needed? It might make sense to use GnuTLS or libgcrypt instead for license reasons - No // comments, please use /* */ comments instead, there are still some compilers that don't like them in C code - Add your real name at the head of the source code files for the copyright. some nickname won't give you anything - You could use the GLib base64 implementation instead of your own - Where does the AES code come from? Also, doesn't openssl/libgcrypt provide this already anyway? :) - No declarations after statements, i.e. move all variable declarations at the start of a block (same reason as for the // comments) Apart from that the code looks really good and clean, I like it :)
> - Could you attach it as a diff to gst-plugins-bad, including build system > modifications? I'll do the diff once the other points done . > - Why exactly is the openssl needed? It might make sense to use GnuTLS or > libgcrypt instead for license reasons Sure. I'll work on the gcrypt use instead of openssl (random bytes, RSA public key encryption). > - No // comments, please use /* */ comments instead, there are still some > compilers that don't like them in C code > - Add your real name at the head of the source code files for the copyright. > some nickname won't give you anything > - You could use the GLib base64 implementation instead of your own > - Where does the AES code come from? Also, doesn't openssl/libgcrypt provide > this already anyway? :) > - No declarations after statements, i.e. move all variable declarations at the > start of a block (same reason as for the // comments) > > Apart from that the code looks really good and clean, I like it :) > Thank you very much for for your advise and your time.
> - Could you attach it as a diff to gst-plugins-bad, including build system > modifications? I'll do the diff once the other points done ans the sink ready. > - Why exactly is the openssl needed? It might make sense to use GnuTLS or > libgcrypt instead for license reasons Sure. I'll work on the gcrypt use instead of openssl (random bytes generation, RSA public key encryption). > - No // comments, please use /* */ comments instead, there are still some > compilers that don't like them in C code This is my C++ habits... I'll substitute the //. > - Add your real name at the head of the source code files for the copyright. > some nickname won't give you anything That is the point : RAOP is an Apple protocol which overlaps RTSP (as far as I know, it has not been published yet) with an extra challenge-response RSA based authentication step. The public key has been extracted by Jon Lech Johansen enabling theard party software to stream data to an AirPort Express (emulating an iTunes identification). I'm not sure this is perfectly legal. What do you think about that ? > - You could use the GLib base64 implementation instead of your own I had the statements and made a copy/paste, unpatient to see if the sink was working... I'll replace the base64 with the glib's one. > - Where does the AES code come from? Also, doesn't openssl/libgcrypt provide > this already anyway? :) It seems that gcrypt now provides the Rijndael algorithm. The AES code comes from a published Rijndael C++ class (I've forgotten the exact source I found). Anyway, I'll do some investigations to see how to use gcrypt on this point. > - No declarations after statements, i.e. move all variable declarations at the > start of a block (same reason as for the // comments) C++ habits once again... I'll move the declarations. > Apart from that the code looks really good and clean, I like it :) Thank you very much for for your advise and your time.
The legality of doing the reverse-engineering may well be dubious in some jurisdictions. I'm pretty sure there's no issue with writing code that uses this information that OTHER people have reverse engineered.
Yes, that was my understanding of this stuff too
(In reply to comment #6) > Yes, that was my understanding of this stuff too > I've been working on the gcrypt's use. The AES section works perfectly but the RSA provided API seems to be missing a requirement : the OAEP padding support. The documentation is not really clear on this point ! This is the only point that would disable using gcrypt. Do you have any knowledge on this point ? Would you accept the plugin with openssl if not possible ?
That's fine IMHO, using gcrypt could be done later :) IIRC the problem with the openssl license is only GPL incompatible and as such we can include it in gst-plugins-bad :) If you provide an updated patch I'll commit it after freeze
Jérémie, any news on this?
(In reply to comment #9) > Jérémie, any news on this? I'm working on the autotool layer; gives me some headeck... Moreover, I'm in vacation with no connection available. So, I'll upload an update in 2 weeks (when back to work and connected).
If you want you can attach the patch without the autotools magic, I'll do that then ;)
I gave this a try today, at last. For me, it manages to connect fine, and output some sort of audio - but it's all corrupted sound, nothing comprehensible. Does this only work with some airport expresses? Is there a test pipeline you'd recommend trying?
Created attachment 116705 [details] AirPort Express Sink and mixer interface sources Autotool layer to be set
(In reply to comment #11) > If you want you can attach the patch without the autotools magic, I'll do that > then ;) > That's really nice from you. Find the attachement below then :-p. Thanks.
I tried a bit more yesterday - turns out that it was occasionally producing some sound. Often it started out (for half a second or so) perfectly, but then started glitching, etc. Looked like some sort of problem with how fast it was sending data - I tried sync=false, but no luck. I noticed at least one bug: in gst_apexraop_write(), you allocate a buffer 3 bytes too short (the ALAC frame header), and then use the shorter length. I guess this discards 3 bytes of valid audio data from each frame? Fixing this didn't make it work for me, though.
(In reply to comment #12) > I gave this a try today, at last. For me, it manages to connect fine, and > output some sort of audio - but it's all corrupted sound, nothing > comprehensible. > > Does this only work with some airport expresses? Is there a test pipeline you'd > recommend trying? > I made the test on my Apple Base Station V6.3. Just to be clear, this is an Airport Express not an Airport Extrem as Apple provides two different products. I use simple pipelines as : "gst-launch [--gst-debug=apexsink:5] filesrc location=my.mp3 ! mad ! audioresample ! audioconvert ! apexsink host=my_apex_ip volume=100" and it works very well about the given sound. As far as I know (attempting while coding) The only reasons that might give a noise in place of a clear sound are : - a wrong plublic RSA key (may be you use a more recent firmware than me and apple changed the key [that's quiet not possible]) - OpenSSL not supporting OAEP padding (RFC 2437), as far as I know, if openssl is build with external RSA RSAref implementation, it should be patched to use its own . I discovered this padding support issue while trying to use gcrypt that does not implement it. - it happened to me with some "misencoded" files, - a wrong format, bitrate, endianess, un/signed, width or depth but the caps should be automatically negociated... I just uploaded new sources. Please let me know if you still experience those mistakes. Could you tell me about your Airport Express firmware and openssl version please ?
(In reply to comment #15) > I tried a bit more yesterday - turns out that it was occasionally producing > some sound. Often it started out (for half a second or so) perfectly, but then > started glitching, etc. > > Looked like some sort of problem with how fast it was sending data - I tried > sync=false, but no luck. I've added a sleeping time between frames in the new uploaded code to avoid apex buffer potential saturation. > I noticed at least one bug: in gst_apexraop_write(), you allocate a buffer 3 > bytes too short (the ALAC frame header), and then use the shorter length. I > guess this discards 3 bytes of valid audio data from each frame? Fixing this > didn't make it work for me, though. > This is absolutely right. As you saw, the true length does not change the output audio result... In fact, I did not find already the right alignement for this section. It just discards one and half a sample per frame. Anyway, I'm working on it too. Hope the last post and updated ccode will help you debug or give me some additionnal informations.
(In reply to comment #17) > (In reply to comment #15) > > I tried a bit more yesterday - turns out that it was occasionally producing > > some sound. Often it started out (for half a second or so) perfectly, but then > > started glitching, etc. > > > > Looked like some sort of problem with how fast it was sending data - I tried > > sync=false, but no luck. > > I've added a sleeping time between frames in the new uploaded code to avoid > apex buffer potential saturation. > > > I noticed at least one bug: in gst_apexraop_write(), you allocate a buffer 3 > > bytes too short (the ALAC frame header), and then use the shorter length. I > > guess this discards 3 bytes of valid audio data from each frame? Fixing this > > didn't make it work for me, though. > > > > This is absolutely right. As you saw, the true length does not change the > output audio result... In fact, I did not find already the right alignement for > this section. It just discards one and half a sample per frame. Anyway, I'm > working on it too. Hope the last post and updated ccode will help you debug or > give me some additionnal informations. > I solved the 3 bytes issue. The sink does not glitch anymore. Please find the new tarball. Autotools still to be written. Enjoy and tell me about your test.
Created attachment 117360 [details] AirPort Express audio sink sources The AirPort Express audio sink implements the mixer interface and now provides read only properties about the airport jack status and type too.
Looks great, needs -fPIC compiler flag to compile on 64 bit though.
Just an indication for those who wouldn't have in mind how to make your gstreamer prefered based on GUI automatically stream data to your Air Port Express. Once the ApEx sink has been installed, just execute : gconftool -t string --set /system/gstreamer/0.10/default/musicaudiosink "apexsink host=xxx.yyy.zzz.www" where xxx.yyy.zzz.www is your Air Port IP address. To retreive your previous configuration, execute : gconftool -t string --set /system/gstreamer/0.10/default/musicaudiosink autoaudiosink Tested with Rhythmbox. Have fun.
Ok, I'm cleaning some things up now, integrating it into the autoconf/automake foo and will commit it later or tomorrow then :)
Ok, committed with some changes to fix some compiler warnings, etc :) 2008-08-28 Sebastian Dröge <sebastian.droege@collabora.co.uk> Patch by: Jérémie Bernard <gremimail at gmail dot com> * configure.ac: * ext/apexsink/LGPL-3.0.txt: * ext/apexsink/Makefile.am: * ext/apexsink/gstapexplugin.c: (plugin_init): * ext/apexsink/gstapexraop.c: (g_strdel), (gst_apexraop_send), (gst_apexraop_recv), (gst_apexraop_new), (gst_apexraop_free), (gst_apexraop_set_host), (gst_apexraop_get_host), (gst_apexraop_set_port), (gst_apexraop_get_port), (gst_apexraop_set_useragent), (gst_apexraop_get_useragent), (gst_apexraop_connect), (gst_apexraop_get_jacktype), (gst_apexraop_get_jackstatus), (gst_apexraop_close), (gst_apexraop_set_volume), (gst_apexraop_write_bits), (gst_apexraop_write), (gst_apexraop_flush): * ext/apexsink/gstapexraop.h: * ext/apexsink/gstapexsink.c: (gst_apexsink_jackstatus_get_type), (gst_apexsink_jacktype_get_type), (gst_apexsink_interfaces_init), (gst_apexsink_implements_interface_init), (gst_apexsink_mixer_interface_init), (gst_apexsink_interface_supported), (gst_apexsink_mixer_list_tracks), (gst_apexsink_mixer_set_volume), (gst_apexsink_mixer_get_volume), (gst_apexsink_base_init), (gst_apexsink_class_init), (gst_apexsink_init), (gst_apexsink_set_property), (gst_apexsink_get_property), (gst_apexsink_finalise), (gst_apexsink_open), (gst_apexsink_prepare), (gst_apexsink_write), (gst_apexsink_unprepare), (gst_apexsink_delay), (gst_apexsink_reset), (gst_apexsink_close): * ext/apexsink/gstapexsink.h: Add apexsink for audio output to Apple AirPort Express Wireless devices. Fixes bug #542510.
(In reply to comment #23) > Ok, committed with some changes to fix some compiler warnings, etc :) > > 2008-08-28 Sebastian Dröge <sebastian.droege@collabora.co.uk> > > Patch by: Jérémie Bernard <gremimail at gmail dot com> > > * configure.ac: > * ext/apexsink/LGPL-3.0.txt: > * ext/apexsink/Makefile.am: > * ext/apexsink/gstapexplugin.c: (plugin_init): > * ext/apexsink/gstapexraop.c: (g_strdel), (gst_apexraop_send), > (gst_apexraop_recv), (gst_apexraop_new), (gst_apexraop_free), > (gst_apexraop_set_host), (gst_apexraop_get_host), > (gst_apexraop_set_port), (gst_apexraop_get_port), > (gst_apexraop_set_useragent), (gst_apexraop_get_useragent), > (gst_apexraop_connect), (gst_apexraop_get_jacktype), > (gst_apexraop_get_jackstatus), (gst_apexraop_close), > (gst_apexraop_set_volume), (gst_apexraop_write_bits), > (gst_apexraop_write), (gst_apexraop_flush): > * ext/apexsink/gstapexraop.h: > * ext/apexsink/gstapexsink.c: (gst_apexsink_jackstatus_get_type), > (gst_apexsink_jacktype_get_type), (gst_apexsink_interfaces_init), > (gst_apexsink_implements_interface_init), > (gst_apexsink_mixer_interface_init), > (gst_apexsink_interface_supported), > (gst_apexsink_mixer_list_tracks), (gst_apexsink_mixer_set_volume), > (gst_apexsink_mixer_get_volume), (gst_apexsink_base_init), > (gst_apexsink_class_init), (gst_apexsink_init), > (gst_apexsink_set_property), (gst_apexsink_get_property), > (gst_apexsink_finalise), (gst_apexsink_open), > (gst_apexsink_prepare), (gst_apexsink_write), > (gst_apexsink_unprepare), (gst_apexsink_delay), > (gst_apexsink_reset), (gst_apexsink_close): > * ext/apexsink/gstapexsink.h: > Add apexsink for audio output to Apple AirPort Express Wireless > devices. Fixes bug #542510. > I'm glad it's been committed :-) Thanks for your autotools work.