trenskow / AirFloat

Implementation of AirPlay audio (AirTunes) for iOS.
510 stars 112 forks source link

multiple instances of AirFloat in one network #37

Open johndoe8967 opened 10 years ago

johndoe8967 commented 10 years ago

Hi,

first of all great work :-) I downloaded and compiled for my iPhone 4s and my iPad. Worked on both of them individually great.

But when both are running on the same time only the first is visible (e.g. in iTunes)

I analyses it a little bit and found out:

I use iOS 7.0.4 with the actual Xcode

best regards and a merry XMAS john doe

johndoe8967 commented 10 years ago

ok, I found out why :-)


Now iOS 7 devices – are always returning a MAC address of 02:00:00:00:00:00. So better use [UIDevice identifierForVendor]. so better to call this method to get app specific unique key

Category will more suitable

appcornerit commented 9 years ago

Changing the MAC address it works great with multiple instances, so for example it's possible to use Airfoil to stream a movie's sound to multiple iPhone as headphone wireless. Great app, thanks!

yfliao commented 8 years ago

Dear All,

Could you share how to solve this issue? Especially, how to modify the code?

Have a nice day!

Best Regards, yfliao

ataibarkai commented 8 years ago

If anyone struggles with this in the future:

The bonjour device identifier is given by CFStringRef combined_name = ...

in the zeroconf_raop_ad_create(uint16_t port, const char *name) function which is in libairfloat/Server/Bonjour/zeroconf_apple.c.

Naively all that is required is to generate combined_name using iOS7+-compatible methods rather than using the MAC address, namely [[[UIDevice currentDevice] identifierForVendor] UUIDString].

However if we only change the identifier here, AirFloat does not work properly. It is found by devices on the network, but as soon as playback starts it switches out of the AirFloat and back to the device's speaker. I was just looking for a quick and dirty solution so don't know where the underlying problem comes from.

I guessed that there is some implicit dependency between the value of combined_name and the function originally used to generate it, hardware_identifier() defined in libairfloat/Tools/Hardware/hardware_apple.c

So I went back and changed hardware_identifier() directly. Success! Multiple AirFloats playing around the apartment!

Any solution that uniquely generates hardware_identifier() for each device should do, but if anyone wants mine (again, quick and dirty):

// -----------------------------------
//  DeviceIDRetriver.h
// -----------------------------------

#include <CoreFoundation/CoreFoundation.h>

uint64_t iOSdeviceID();
// -----------------------------------
//  DeviceIDRetriver.m (ARC-managed)
// -----------------------------------

#import "DeviceIDRetriver.h"
#import <UIKit/UIKit.h>

uint64_t iOSDeviceID() {

    uint64_t returned = 0;

    // get ID string
    NSString *idString = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

    // convert to data, then store sufficient data into uint64_t.
    // this is a crude NSString -> uint64_t hash
    NSData *idData = [idString dataUsingEncoding:NSUTF8StringEncoding];
    [idData getBytes:&returned length:sizeof(uint64_t)];

    return returned;
}

and now in hardware_apple.c (don't forget to #include "DeviceIDRetriver.h"):

uint64_t hardware_identifier() {

    return iOSDeviceID();
}