After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 542510 - [apexsink] Apple AirPort Express Wireless Sink
[apexsink] Apple AirPort Express Wireless Sink
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-bad
0.10.15
Other Linux
: Normal enhancement
: 0.10.9
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2008-07-11 11:27 UTC by Jérémie Bernard
Modified: 2011-01-06 07:30 UTC
See Also:
GNOME target: ---
GNOME version: 2.19/2.20


Attachments
APEX sink plugin sources (29.38 KB, application/x-compressed-tar)
2008-07-11 12:08 UTC, Jérémie Bernard
Details
AirPort Express Sink and mixer interface sources (12.17 KB, application/x-compressed-tar)
2008-08-15 19:27 UTC, Jérémie Bernard
Details
AirPort Express audio sink sources (13.40 KB, application/x-compressed-tar)
2008-08-25 19:09 UTC, Jérémie Bernard
Details

Description Jérémie Bernard 2008-07-11 11:27:17 UTC
Sink definition : stream raw input sound to an Apple AirPort Express (simple ALAC encapsulation, RAOP control definition, data AES RSA encryption).
Comment 1 Jérémie Bernard 2008-07-11 12:08:12 UTC
Created attachment 114385 [details]
APEX sink plugin sources
Comment 2 Sebastian Dröge (slomo) 2008-07-13 20:44:59 UTC
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 :)
Comment 3 Jérémie Bernard 2008-07-16 09:42:19 UTC
> - 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.
Comment 4 Jérémie Bernard 2008-07-16 10:06:25 UTC
    > - 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. 

Comment 5 Michael Smith 2008-07-16 16:47:30 UTC
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. 
Comment 6 Sebastian Dröge (slomo) 2008-07-16 17:38:08 UTC
Yes, that was my understanding of this stuff too
Comment 7 Jérémie Bernard 2008-07-20 20:56:53 UTC
(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 ?
Comment 8 Sebastian Dröge (slomo) 2008-07-21 10:20:48 UTC
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
Comment 9 Sebastian Dröge (slomo) 2008-08-02 17:17:00 UTC
Jérémie, any news on this?
Comment 10 Jérémie Bernard 2008-08-07 19:42:43 UTC
(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).
Comment 11 Sebastian Dröge (slomo) 2008-08-08 09:08:22 UTC
If you want you can attach the patch without the autotools magic, I'll do that then ;)
Comment 12 Michael Smith 2008-08-15 01:33:55 UTC
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?

Comment 13 Jérémie Bernard 2008-08-15 19:27:00 UTC
Created attachment 116705 [details]
AirPort Express Sink and mixer interface sources

Autotool layer to be set
Comment 14 Jérémie Bernard 2008-08-15 19:28:15 UTC
(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.
Comment 15 Michael Smith 2008-08-15 19:41:48 UTC
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.
Comment 16 Jérémie Bernard 2008-08-15 21:13:31 UTC
(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 ?
Comment 17 Jérémie Bernard 2008-08-15 21:20:39 UTC
(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.
Comment 18 Jérémie Bernard 2008-08-25 19:04:36 UTC
(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.
Comment 19 Jérémie Bernard 2008-08-25 19:09:14 UTC
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.
Comment 20 Gabriel Burt 2008-08-27 03:44:18 UTC
Looks great, needs -fPIC compiler flag to compile on 64 bit though.
Comment 21 Jérémie Bernard 2008-08-27 19:59:11 UTC
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.
Comment 22 Sebastian Dröge (slomo) 2008-08-28 16:53:32 UTC
Ok, I'm cleaning some things up now, integrating it into the autoconf/automake foo and will commit it later or tomorrow then :)
Comment 23 Sebastian Dröge (slomo) 2008-08-28 17:00:26 UTC
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.
Comment 24 Jérémie Bernard 2008-08-29 11:35:10 UTC
(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.