Seamless music playing across web pages round-up (+examples +code)
Comments
http://mokele.co.uk/code-examples/seemless-music/
its not working. i hv downloaded the code, but i could not play the music
You’d have to debug it to find out why it doesn’t work. That code is only an example, and may not work out of the box.
You missed http://amiestreet.com/ as well — it’s sort of a hybrid. Facebook-style ajax pages with hash tag (only while playing), or popout.
Yeah, one of the guys there (that I assume that you know ;) linked me to the js file for that shortly after writing this. Looked pretty good.
I’ve also abstracted out a new version of the page navigation overrides with javascript that is used for http://holyroarrecords.com/ which is at http://github.com/mokele/navigation.js and way better than my examples here.
after lots of research, I found this code. I checked out the navigation.js too. I’m not a developer — just a user. But I know just enough to be a little dangerous.
So I need to as ask rather dumb question: does the navigation.js code go onto each page, or just the index, or is the code you provided supposed to be divided up (for folks who know what they’re doing.)
You’re right, sorry about that VaDesigner, I haven’t made any user end howto on how to use navigation.js. I’ll try and write on soon.
The basic method of using it is to script include it and [HTML_REMOVED]prototype.js[HTML_REMOVED] in the head of your page. After this all form submits and link clicks will be routed to an iframe which repeats the same request but with the added __backgroundLoad=1 get or post variable.
What you do from there is up to you. I regularly cause that page load to return a script tag with a little javascript to update the window.parent somehow, normally by removing the old content and adding some new content to it dynamically, but only when the __backgroundLoad param is found.
that’s http://www.prototypejs.org/
gotta change the markup rules ;p
I for example can’t stand websites that are playing continuous music while navigating. If for example I am listening to music while navigating and stumble upon a website which plays music and I can’t stop it I get very frustrated and don’t visit that website anymore. I really don’t think that playing music on a website is a good idea. Just my 2 cents.
Based on Lucas Gonze‘s entry 100% in-page navigation for music sites I thought I’d do a round-up of the different ways in-which you can provide a seamless music playing experience across the whole of a website.
The methodology behind playing music on web pages changes depending on your needs and the design of the site, but what is pretty much a requirement is a Flash player somewhere on the site that does the actual playing part. The problem then becomes where to put it, because wherever you do put it, someone’s hopefully going to be navigating away from there to another page on the same site causing the swf to be destroyed and then reloaded on the new page leading to an interruption in playback. There are however a number of different approaches that sites have adopted to circumvent stream interruption, and some additional hackery that I’ve been playing with, so let’s have a look at all that.
One big flash player / website
If we’ve got a flash audio player, why not make the whole site one big pile of flash? Answer — as well as locking your developers into the death-trade that is flash for web page development, the site won’t actually feel like a web page what-so-ever. This is in my opinion is an incredibly bad idea. We should only be using Flash for the purpose of handling the audio since that’s the most available method of doing so. Want to develop a website? Use (X)HTML, CSS, JavaScript, and a little Flash in moderation please.Docked player in a frame
If we make our index page a <frameset /> then we can pin our swf and controls into a frame that doesn’t get reloaded, leading to continuous playback. Many sites do this with a frame at the top or bottom and normally with a static list of tracks. This method does work great, but what a lot of sites miss is that once we’ve put the visitor inside some frames they no longer have a permalink to the subpage they’re on in their browser’s address bar. This could stifle the amount of links being shared by your visitors, and causes an unintuitive lock-in experience.Another downside of a docked player is that we’ve wasted some space on our site. Normally we’ve got a header with a logo, some navigation, ads, and then our main content, and if we then add a docked player frame that doesn’t get scrolled off the page when we read below the fold we’re taking up an extreme amount of very precious vertical real estate (hooray for marketing terms!). The fact that it’s docked to one edge of the site is however very good for our visitor’s experience since they’ll know exactly where the music’s coming from, and more importantly have access to those amazingly useful stop and pause buttons.
Player in a popup
We’re saving layout space and we’ve got continuous playback, you’d think that popup’s tick all the boxes, but the fact that it’s a popup just causes me to cringe. Granted they do add 1 feature that all other methods don’t have, that being the ability for the visitor to actually leave our site entirely and still have that playback going. But the downside of that is we’re more than likely going to have to put a lot of meta-data in that popup’s layout as well, making it into a mini-site mashup of crap that ends up just getting bigger and bigger. Worse than that is that we will probably have some ad requirements too that are going to have to be shoved into that popup. I don’t want to write about popups any longer.Player in a hidden frame with reloadable controls
The docked player version is great, but that vertical space is still very much important to me, so what we can do to improve that is by making that frame completely hidden with a height of 0%. Once we’ve done this we’re going to have to put all the player controls into our main layout and talk to the player through the frame’s window via JavaScript.On the loading of the frameset the first page to be loaded into the content area is given the hash anchor #loadingPlayer which tells it that it needs to wait until the player frame contacts it to tell it that the player is loaded and ready to be interacted with. On subsequent pages linked from there we add an onload handler that won’t find this hash so will call ping() on the player frame to say that it’s ready for the player callbacks. This way we can do player initialisation and playstate checking both when we first initialise the player frame and when a new page loads after the player may already be playing. For this example we’re using SoundManager2, and the code for the full project explained in the rest of this entry is available on github.
//on all content pages we have this JavaScript
//and initPage is called onload
function soundManagerLoad() {
var player = window.parent['player'];
//bind some functions we defined in player.html
//into this page scope
soundManager = player.soundManager;
playStream = player.playStream;
stopStream = player.stopStream;
changeSong = player.changeSong;
}
function initPage() {
var hash = window.location.hash;
if(hash != "#loadingPlayer") {
soundManagerLoad();
window.parent['player'].ping();
}
}
// JavaScript from player.html 0% frame
soundManager.onload = function() {
window.parent['content'].soundManagerLoad();
}
function ping() {
if(!sound) return;
if(sound.paused) {
callbacks.onpause.apply(sound);
} else if(sound.playState == 1) {
callbacks.onplay.apply(sound);
}
}
A lot of sites do this already when implementing the docked and popup player versions giving them the ability to change the song to one referenced or clicked on within the content area. But there isn’t much stopping us from also taking all the other controls along to the other side of the frame border. Once we’ve done this can style the player controls however we like using out general (X)HTML, CSS, and JavaScript abilities tools. This example just adds the bare minimum for us to play, pause, stop, and change the stream, but I’d advise using SoundManager itself from inside your content areas along with any interface code instead of putting that all in player.html like I’ve done.
A downside of the hidden frame example is again like the other frames example, we don’t have a changing url when delving into subpages of our site. But there’s a number of hacks we can apply to our site that’ll make it possible to add some deep linking and url changing when browsing further to those subpages which I’ll attempt to explain and give an example of.
More Hacks
So now we’ve got some continuous playback without restricting our layout design and development toolset, but now what we need to do is get the visitor’s browser url to change when moving around the site since the frames solution to continuous playback prevents it from doing so. The only way we can currently deal with that is by altering window.parent.location.hash on each page-load that represents the # anchor part of urls. This is a method which a lot of sites have started to do recently when wanting to alter the current page based on AJAX’d content (e.g. Facebook and HypeMachine).// JavaScript on every content page
function checkHash() {
var hash = window.location.hash;
if(hash == ""
&& window.parent.location.pathname != window.location.pathname) {
window.parent.location.hash = window.location.pathname;
}
}
// we can call this right away before page-load
checkHash();
This does however introduce yet more problems, since if someone shares that link or does a refresh of the whole frameset then we won’t actually be on the page we thought we were on, so we’ll have to introduce an onload handler of one of our frames that checks for the # part and redirects the content pane accordingly. We would do that server-side, but unfortunately browsers don’t send the # part of the request URI.
// JavaScript in player.html
function checkHash() {
var parentHash = window.parent.location.hash;
if(parentHash.indexOf('#/')==0) {
window.parent.location.href = 'index.php?p=' + parentHash.substr(1);
}
}
// again we can do this right away before page-load
checkHash();
We’re redirection back to our index page here with a ‘p’ GET parameter so that the we can then adjust what the default content frame src in our new frameset instead of our default one. You can see here our #loadingPlayer anchor that was mentioned earlier that forces the page we visit to wait for player.html to tell it that soundManager is ready.
<?php
$page = isset($_GET['p']) ? htmlentities($_GET['p']) : 'page1.php';
?>
<html>
<head>
<title>Hidden Frame Example</title>
</head>
<frameset rows="100%,0%" frameborder="0">
<frame src="<?php echo $page ?>#loadingPlayer" name="content" />
<frame src="player.html" name="player" />
</frameset>
</html>
This is not exactly great. In-fact it’s pretty damn ugly, and I have no idea how it’d affect SEO, but at least it gives us continuous playback and shareable urls. Not being able to get at the # part of a URI server side is a big downside to this since the page starts loading before a redirect might occur. It would also be a pretty good idea if we could send perminant HTTP redirects via JavaScript, but no, we can’t. Well not that I can see.
Update: AJAX’d in Content
If you follow a similar window.location.hash alteration from the hidden frame example above, but instead of doing it onload you can add a JavaScript hook to grab any <a /> tag click, stop the event, alter the hash, do an AJAX call to get the new page’s content, and then replace the current content and move back up to the top of the page. This can be done a lot more elegantly than the Frames version, but make sure you still have working perma-links.So I guess in conclusion it’s still rather annoying to have a site that has continuous music playback through Flash, and the most ideal solution/hack that I could come up with ends up having some very weird side-effects. Let’s try and see if we can’t come up with something nicer. Let me know if you come up with something or find somewhere doing it another way.
The working hidden frame example is available at http://mokele.co.uk/code-examples/seemless-music/ and the code is available on github.
Update I’ve had another look at HypeMachine which I previously thought didn’t do seamless playback, but the reason why that is is because I was logged-out. While logged-out HypeMachine will follow links normal and give you playback with interupts between pages, but when logged-in you’ll get ajax’d content hash altering seamless playback. Big props to Anthony and the team on that one. If you take the frame example and remove the frame specific aspects and replace links with ajax’d content then you’ll manage something similar.
Update 2 Safari doesn’t seem to like the frames and always reloads the whole page when loading new pages, so it’s most probably best to do the ajax’d in content loading method that HypeMachine and Facebook adopt. Even with target=”content” on all links in the content area Safari still reloads the whole frames, so if anyone has any info on that that’s be great so we can include it here.
Update 3 Based on the work I’ve done at http://holyroarrecords.com/ I’ve abstracted out much better code to handle page navigation which is available and open for contribution at http://github.com/mokele/navigation.js
Check out this one: http://adnsto.net/scmplayer/
It looks like he’s using a combination of php and javascript to embed a very nice player into the site. However, he certainly doesn’t seem to want to share the code…
Works very well though (except for when his servers are down… see his forum for posts on that)