I have found a bug using the external controls for the html5 widget on iOS, i have tested with iphone and ipad. The controls inside the widget work ok. However on my clients site http://www.bushytunes.net and the widget api playground http://w.soundcloud.com/player/api_playground.html the external controls run an error.
Here is what the console from the widget playground prints:
SC.Widget.Events.PLAY {"loadedProgress":null,"currentPosition":0,"relativePosition":0}
SC.Widget.Events.PAUSE {"loadedProgress":null,"currentPosition":0,"relativePosition":0}
SC.Widget.Events.PLAY {"loadedProgress":null,"currentPosition":0,"relativePosition":0}
SC.Widget.Events.PLAY {"loadedProgress":null,"currentPosition":0,"relativePosition":0}
SC.Widget.Events.PLAY {"loadedProgress":null,"currentPosition":0,"relativePosition":0}
SC.Widget.Events.READY {}
Loading...
Thanks, James
TL;DR: iOS 6 should work with a limitation of a call to play to be init by user action, iOS5 and below probably won't get a fix.
We'll try to resolve this with some kind of a hack, but most probably this won't get a proper solution any time soon.
SoundCloud Widget is using HTML5 Audio to play sounds on iOS. There are two limitations on starting playback in iOS:
- Playback must be started by user action (so within event handler)
- The call to
audio.play
method has to be within synchronous call stack of that event handler.
This means, that this works:
document.querySelector('.play-button').addEventListener('click', function () {
audioController.play();
}, false);
But this doesn't:
document.querySelector('.play-button').addEventListener('click', function () {
setTimeout(function () {
audioController.play();
}, 500);
}, false);
Cross-domain communication between iframes is only possible in asynchronous manner. Our implementation is using postMessage
DOM API, but even older techniques such as Fragment Identifier Messaging (FIM) that is using location.hash
are asynchronous. This means we don't currently see a way of enabling playback through API for iOS5 and below (as there is also no Flash fallback).
However, there are also good news: iOS6 has dropped the limitation No2. This means that as long as the API call to play
is called by user action, you'll be able to play sounds. Even though the communication between your parent window and widgets' iframe is still async. Unfortunately iOS hasn't dropped this limitation.
I hope this helps and I'll update this answer in case we find a proper workaround.
My suggestion would be to build your own custom player with a library like Audio5JS or SoundManager2 in case controlling playback on iOS is crucial for your app.
You can see vague description of what I am talking about on developer.apple.com resource.
I can't completely tell if @gryzzly is trying to say this, but the Widget API's external controls are completely broken on mobile. The answer does explain why -- you can't synchronously tell the iFrame to play the sound, but it is my understanding that proper iframe.contentWindow calls would be synchronous? I may be wrong.
Try directing your mobile phone to the widget API playground: https://w.soundcloud.com/player/api_playground.html
Even there it doesn't actually play unless you press the orange button.
Pretty irritating since there's no application to get around the streaming API limit either. There seems to be literally no way to get a site that may experience more than 15,000 requests/plays per day to work with SoundCloud on mobile. I just want continuous music playback.