June 25, 2003
Shared Library Secrets

Using Shared Libraries (SL) in Flash is still quite an adventure, similar to crossing the Pacific Ocean on a surfboard. It theoretically works, but you will need good preparation and be ready to expect trouble. Unfortunately in the past SL were really buggy so lot's of people avoided to use them and didn't touch them since. Let me tell you this: I have built two big sites now that rely heavily on Shared Libraries and I think I can say now: Shared Libraries do work!

For the general use there is some documentation on this on the Macromedia Site: Using shared libraries also the Flashcoders WiKi has quite a lot of stuff to contribute, though some of it is perhaps a little bit outdated.

If you are planning to use Shared Libraries, make sure that you (and your visitors) at least use Flash Player 6.0.65 (6.0.67 for Macs, 6.0.69 for Linux) as Macromedia adressed some issues in that release:

Release Note:
The current limitation of the player is that you can only do one-tier shared libraries (Runtime Shared Libraries to consumer SWF). Developers now have the ability to do multi-tier dependent shared libraries.

Runtime Shared Libraries improvements:
- Support for multi-tier Runtime Shared Libraries.
- Double-byte functionality.
- Ability to handle complex Runtime Shared Libraries including components.
- Timing issues with Runtime Shared Libraries are now resolved.

The principle of a shared library is that you put in all elements that get used by more that one swf movie. This will save you a lot of unnessary reloading of the same data. For example: I add one basic circle to the library and reuse it all the time by scaling and colorizing it. Same with one basic square. The biggest bytesaver is of course to share fonts, but that's a pretty delicate thing which is very nicely described by Branden Hall. There is also a technote by Macromedia themselves: Using Font Symbols

Because the elements in the Shared Library are reused by other movies Flash has to make sure that these elements are present already when the movies need them. That's why it tries to load them at the very beginning. I say it tries, because this process doesn't work all the time if you do it without preparation. What happens (especially in real life dial-up situtations) is that the main swf loads, it discovers that it uses a shared library and starts loading that. But Flash is a streaming format, so instead of waiting for the shared library to finish loading it sometimes continues with the main movie. Now that main movie might request an item from the library which is not loaded yet. Unfortunately that's something which is not defined in the Flash format specifications. Assets have to be present before they are used. In a case like this you will see nothing or the whole movie hangs. So what's the solution? You have to make absolutely positively sure that the shared library has loaded before anything else happens. Which means: use a preloader. Even better: use a preloader movie for the main movie. I'm using the following scheme and until now it works stable:

preloader.swf:

this.createEmptyMovieClip("dummy",0)
this.createEmptyMovieClip("dummy2",1)
this.dummy._visible=this.dummy2._visible=false
this.dummy.loadMovie("shared.swf") //first preload the shared library
this.onEnterFrame=this.preload1
function preload1(){
if (this.dummy.getBytesLoaded()>100){
if(this.dummy.getBytesLoaded()==this.dummy.getBytesTotal()){
this.dummy.loadMovie("main.swf") //also preload the main movie
this.onEnterFrame=this.preload2
} else {
// add some progress display here
}
}
}

function preload2(){
if (this.dummy2.getBytesLoaded()>100){
if(this.dummy2.getBytesLoaded()==this.dummy2.getBytesTotal()){
_level0.loadMovie("main.swf") //now really load and run the main movie
this.onEnterFrame=null
} else {
// add some progress display here
}
}
}

I must admit: using SL still involves sometimes using a little bit of voodoo. For example: I have the habit of using Branden's technique of placing an empty dummy movieclip symbol from the Shared Libray into the first frame of every movie that uses the library. I never checked if it works without that thing, too. Maybe it does, but in this case I go by the old admin's saying: "Never change a running system".

I guess that until here there was nothing new for Shared Library experienced developers. But here's something which might be interesting for you, too:

Mind the cache
I had this strange phenomenon: a few days after the launch of a site I made some changes to the Shared Library. Everything worked fine for me. Only did I receive a few mails from other people that couldn't see anything anymore. It took a while until I asked them about their browser's cache settings. And guess what - in every case it was set to something like "update as seldom as possible". They view the swf which gets served the old library. Of course the internal IDs do not match and flash goes into hibernation mode.

That is indeed a serious problem. Of course I can tell my clients and friends to set their cache to "update on every visit", but I cannot tell that every visitor of a site. The difficulty is that for every normal flash movie, xml or loadVars file you can add a random query string to avoid caching. For the Shared Library you cannot do that as its URL is hardcoded into the swf. So what can you do? Do not change the Shared Library after going live. Haha. Well, I guess that's no solution. If you only need additional symbols and do not need to make changes to existing ones: use a second or third Shared Library. That will mean definitely less work than solution #3: rename the Shared Library. Unfortunately this will mean that you will have to go into every movie that uses this library and edit the URL inside every imported symbol. That's not really fun. I hope Macromedia will find some solution for this in the Future. The best solution would be the ability to dynamically set the name of the Shared Library. Either from the object tag or via actionscript.

Dynamically Shared Libraries
Speaking of Dynamically Shared Libraries. Here is something I haven't read anywhere else. Did you ever think of replacing "sharedlib.swf" with "sharedlib.php"? Why should you? For a normal site this is not really interesting, but if you go multilingual - I mean real multingual, not English, German, French or Italian - I mean Japanese, Russian, Greek, short: if you need different font encodings. Well, then this gets really exiting: instead of doing different swfs or embedding all the fonts you serve different Shared Libraries under the same name. Instead of a static Shared Library you link to a server-side script which serves a different library depending on the country the request comes from. The catch? Unfortunately flash does not include a referrer header when it's downloading the Shared Library. So the PHP script gets no clue from the request itself which language it shall serve. But it knows its own server name. From that it can decide which library to send, is it mysite.com, send shared_western.swf, is it mysite.ru, send shared_cyrillic. Alternatively you could create subdomains: europe.mysite.com, russia.mysite.com, japan.mysite.com. Of course all the domains have to point to the same directory.

It came just to my mind that it might be worth to look into PHP sessions for this purpose - that could lead to a more generic solution which would allow even more flexibility, it might enable you to control which library to serve before the flash file even loads. Something more experimental could be to serve random libraries that use the same symbol or font names, but are different. You could have different templates depending on daytime. That is not tested yet, but I think I should give it a try...

Posted at June 25, 2003 07:15 PM | Further reading
Comments

Great article ! Bookmarking this one for sure ...

Posted by: DW on June 26, 2003 10:35 PM

Oh, I just discovered that Jesse Warden has also recently posted something about Shared Libraries: http://www.jessewarden.com/archives/000180.html

Posted by: coma2mario on June 27, 2003 10:43 AM

I created a swflib manager C++ dll that runs on the web server. On each client connect it calls the lib manager with all required settings which gets saved for that session and returns a session id. It works quite well ;p

e.g:

in the swf export link ids are set to:

/libserv/swflibman.dll/id=

e.g.

/libserv/swflibman.dll/id=CLANG

the swflibman.dll is placed in a subdir on the webroot and is accessable to all from there.

in the swf that uses the libs I drop a copy of the the
LibLink component and at preload time:

LibLink.addLib( "CLANG" );

LibLink.setLibParam( "CLANG", "RUSSIAN" );

LibLink.loadLibs();

and a callback that allows the movie to progress after load or show an error.

The LibLink component basically keeps a list of libraries used, sets their parameters and loads em.

It also checks the server for any lib dependencies and loads those as well in order...

hope that helps...


Posted by: neo binedell on August 5, 2003 06:31 PM

Here in this site i have seen a gliding menu on the top of the screen....that was very cool and I request u to teach me that [gliding menu].......I hope u won't discard my request.....


Hoping to hear from u very soon

Posted by: atish chitrakar on August 15, 2003 12:18 PM

Thanks for the resource.

We are having particular troubles with using sounds from shared libraries. All of Macromedia's documentation refers to non-existant web pages. Would you consider adding commentary on sounds via shared libraries to your site (of point me to it if it is already there)?

Thanks in advance for any reply or info.

Posted by: Jeff Hawkins on October 17, 2003 08:06 PM

How about...
"sharedlib.php?lang=ru"

Posted by: bruce on March 25, 2004 01:37 PM

bruce: as it's not possible to change the reference to the shared library at runtime this will not help much.

Posted by: Mario on March 25, 2004 01:50 PM

did anyone come across this shared lib issue:

i got a source movie which deals with form-tweening masks to manipulate some dynamically fed jpg images. if i would load those jpgs directly into my source movie, they would appear on their first frame, but get lost with the next keyframe containing an instance of the original placeholder mc or masking/formtweening key.

so the easy way around this seemed: work with a small shared library providing those jpgs. it works perfectly as long as the library movie is not dynamically fed with the jpgs. my source movie imports the library before the library itself loads its jpgs from the server.

can i control the timing of the import or something ?! thanks a lot 8)

Posted by: Martin on March 31, 2004 05:16 PM

im seriously gettin mad... WTF are u loading in dummy2???


thx, rudi

Posted by: rudi on April 26, 2004 07:47 PM

it doesnt work with me. i too dont know what dummy2 does mean.
i looks nice, but doesnt work at all.
(flash 7, mx2004)

Posted by: joni on August 25, 2004 03:33 PM

I guess this need to been changed :

this.dummy.loadMovie("main.swf") //also preload the main movie

by : this.dummy2......

so when the function preload2 is called there's something to load .

But I've got an issue while trying to load on _level0 :
It seems that the function preload2() is delete when _level0.loadMovie function is called !?

Posted by: lastchildz on November 3, 2004 02:32 AM

The link to Branden Hall's blog is dead. Anyone know the proper archive link?

Posted by: Ben Jackson on November 10, 2004 04:43 PM

Using a shared library seems like a cool idea - but does it have a problem handling components?

I've made a shared library for my project which includes a few fonts and a scrollbar. The fonts work fine, and has saved a about 25kb off each of my section swfs, but the scrollbar doesn't appear as it should.

I've tried making sure that each part of the component is shared individually, but to no avail.

Any suggestions? Or am I being stupid? (good chance of the latter)

Cheers

Bren

Posted by: Brendan Baker on December 16, 2004 12:46 PM

Let's say the url to one of the swf's was a php file, like you mention. Using the method param in mc.loadMovie, you could pass a post variable that tells the php which swf file to return.

I've done this, but the post variable is only sent in Internet Explorer and not a single browser using the netscape plugin architecture. Yay, macromedia!

Anyway, you say you've done something similar before. Any workarounds? I'm out of ideas.

Posted by: Prometh on February 27, 2005 11:32 PM

@Prometh: I my case it definitely works perfectly with PHP Sessions. I do it like this: Before the main swf is loaded I start a PHP session. Then when the main.swf retrieves its dynamic shared library from the shared_library.php script, the script knows which library to serve because I have stored all necessary infos before in the session - in my case it's some language infos (to serve the correct fonts). So there is no need to transfer any variable from flash to the script.

Posted by: Mario Klingemann on February 27, 2005 11:42 PM

Hi gies I have adopted for ease of use the Loader code

global.aClips = new Array();
_global.iFile = 0;
////////////////////////////////////////////////////////
// Files Definition:
//
// First the Libraries
// Last the main movie
////////////////////////////////////////////////////////
_global.aClips[ _global.iFile ++ ] = "SoundLib.swf";
_global.aClips[ _global.iFile ++ ] = "slotNew.swf";
////////////////////////////////////////////////////////
_global.iLoaded = 0;
for ( var i = 0 ; i 100){
if( this["dummy" + _global.iLoaded].getBytesLoaded() == this["dummy" + _global.iLoaded].getBytesTotal() ){
++ _global.iLoaded;
if ( _global.iLoaded < _global.aClips.length ) {
this["dummy" + _global.iLoaded].loadMovie( _global.aClips[ _global.iLoaded ] ); //also preload the main movie
} else {
_level0.loadMovie( _global.aClips[ _global.aClips.length - 1 ] );
this.onEnterFrame = null;
}
} else {
Progress.percent = this["dummy" + _global.iLoaded].getBytesLoaded() / this["dummy" + _global.iLoaded].getBytesTotal();
}
}
}

Posted by: Atanas Krachev on March 23, 2005 09:17 AM

And how about security, shared library and stand-alone projectors ??

For example :

A.swf is on client side, and use __library.swf as shared library.
B.swf is on server side, and loaded by A.swf.
B.swf use __library.swf elements too.

But when I try to load B.swf, I have a sandbox security alert, that (http) B.swf cannot access to (local) __library.swf

Anyone has a solution ? I have tried allowDomain on A to server, but no result...

Posted by: titouille on September 29, 2005 12:07 AM

I am creating a flash photo albu. In that i am loading the images dynamically into a movie clip through php. I want to load all the images at a time.
So how can i gave a preloader till all the images gets loads.

Please help me.

Posted by: Senthil on October 22, 2005 02:05 PM

been having similar woes with shared library caching but recently i've discovered a failsafe way of ensuring caching isn't a problem: use the base parameter in the object/embed tag of the html.

i usually have this set to something like '../swf', but if you include a version number in there, you can upload a new directory for every release and you don't have to change any paths inside the fla - just change base to the correct directory release eg. '../swf/v1.12', '../swf/v1.13' etc. this will mean more files on your server, but it will significantly reduce the download load compared to the getstring method (which you can't use on shared libraries anyway).

One nice extra of this method is you can always roll back the release with a single variable change, if the update is causing problems. Hooray!

Rob

Posted by: rob on November 3, 2005 05:22 PM

Much more annoing problem is cache on proxy. Users can't refresh shared file even if they clean cache in browser. It's really headache..

The way to change all the files in project is bad. Users will have to load all projects files again but the only one little shared swf had changed. Too expensive changes..

Posted by: Fix on December 2, 2005 04:21 PM

There are two links in this page that are not working:

http://www.jessewarden.com/archives/000180.html

http://web.archive.org/web/20021206180401/

and

http://www.waxpraxis.org/archives/000062.html

.....................................................................

Do anyone know how to use shared libraries to load dynamic fonts? Could you please post it here? I need the solution for this issue.

Regards,
Axl Laruse

Posted by: axl laruse on December 12, 2005 11:25 PM

@axl laruse:
the trick is that the two last url's you posted are in fact one.
try to write them together right as they are posted further above
-> http://web.archive.org/web/20021206180401/http://www.waxpraxis.org/archives/000062.html <-
drop me a line and i can email you the whole page in zip if its still not working...

ps: great resource! this page as well as the linked one helped me out a LOT!!! THX!

Posted by: antiplex on February 15, 2006 11:28 PM
Post a comment
Name:


Email Address:


URL:


Comments:


Remember info?



Thank you!

Most Visited Entries
Sketches, Works & Source Code
Lectures
Contact
Backlog
In Love with
Powered by
Movable Type 2.661

© Copyright Mario Klingemann

Syndicate this site:
RSS 1.0 - RSS 2.0

Quasimondo @ flickr
Quasimondo @ LinkedIn
Quasimondo @ Twitter
Quasimondo @ Facebook
Quasimondo @ MySpace
Quasimondo is a Bright
Citizen of the TRansnational Republic
My other blog in german
Impressum


My family name is written Klingemann,
not Klingelmann, Klingeman, Klingaman, Kingemann,
Kindermann, Killingaman, Klingman, Klingmann, Klingonman
Klingemman, Cleangerman, Klingerman or Kleangerman

profile for Quasimondo at Stack Overflow, Q&A for professional and enthusiast programmers