Articles Archive
Articles Search
Director Wiki
 

Detecting a User's Modem Speed

December 11, 2001
by Will Turnage

Hi Multimedia Handyman!

How can I check what connection speed my users are using? What modem speed?

Sincerely,
Ittai Bar-Joseph

Ittai-

Unfortunately, there is no simple way to just call a function and find out the exact speed of a user's Internet connection. The only realistic way to do this in Director is to download a large file from the internet, and then monitor the progress of the download. By measuring how long it takes to download the file based on the size of the download, you can calculate an estimate of the user's connection speed (this is exactly what most browsers' download functions do).. More importantly, this calculation isn't just the theoretical connection speed (i.e. 56Kbps or 1.5Mbps), it's a real world test between the user's computer and your Internet hosting environment.

However, most users would be really annoyed if they had to sit through an unnecessary download just so you have an idea of what their connection speed is like. So the way around it is to incorporate this monitoring check into a loader movie that preloads your actual shockwave movie. This way, you can get a sense of the user's connection speed without inconveniencing them. For instance, check out this Shockwave movie:

When you click on each of the buttons, you will see the progress of the file being preloaded into your cache. As it preloads, it also calculates the approximate download speed you are getting on your individual machine. Now let's look at the code for this movie. [Editor's Note: Each of these buttons will perform its test only once in the current configuration, because once the file is downloaded it is cached by Shockwave.]

On each of the three buttons is a handler, that is set to preload a particular URL. For instance, the button that downloads a 250K file has this behavior attached to it:

on mouseUp me
  preloadFile ("http://will.turnage.com/DOUG/large.png")
end

This code calls the preloadFile handler and passes it the exact URL to download. Now, you need to create the preloadFile handler in one of your movie scripts. Its code looks like this:

global gNetID, gStartTime

on preloadFile whichFile

  gNetID = preloadNetThing (whichFile)
  gStartTime = 0
  timeout ("checkDownload").new (100, #checkDownload)

end

This preloadFile handler uses two global variables: gNetID and gStartTime. The first global, gNetID, keeps track of which network operation Director is currently preloading. The second global, gStartTime, keeps track of the time when the download started. This handler starts by assigning gNetID with the value of the net operation preloadNetThing. Next, it initializes gStartTime by setting it to zero. Finally, it creates a timeout object which will call the handler checkDownload every 100 milliseconds, or approximately ten times a second.

Director will execute the checkDownload handler 10 times a second. That handler looks like this:

on checkDownload

  tempStatus = getStreamStatus (gNetID)
  case tempStatus.state of
    "Complete":
      timeout ("checkDownload").forget ()
    "Started", "InProgress":
      if gStartTime = 0 then
        gStartTime = the ticks
      end if
  end case
  sendAllSprites (#updateDownloadInfo, tempStatus.bytesSoFar, tempStatus.bytesTotal, gStartTime)

end

This handler starts by getting the streamStatus of the preload operation you called earlier. The getStreamStatus function in Director returns a property list in Director that looks like this:

-- [#url: "http://will.turnage.com/DOUG/large.png", #state: "InProgress", #bytesSoFar: 108647, #bytesTotal: 252986, #error: ""]

There are five different properties in this list. The #url property tells you the exact URL that is being downloaded, the #state property tells you what is currently happening with the download. There are five different possibilities for the state value. They are: "Connecting", "Started", "InProgress", "Complete", and "Error". The #bytesSoFar property tells you the number of bytes that have been currently downloaded, and the #bytesTotal property tells you the total number of bytes in the download. Finally, if there is an error, it is returned in the #error property.

In the checkDownload handler, you assign this property list to a local variable name tempStatus. Next, you check the value of the #state property. If the operation has completed, then you forget the timeout object and everything is done. If the #state has just started or is in progress, then you check to see if the global variable gStartTicks is still set to 0. If it is, then you reset its value to the ticks, which is a system property that relates the current time in 1/60ths of a second. Finally, you use a sendAllSprites command to call the updateDownloadInfo handler in each of the different sprites on stage.

There are different behaviors on the progress bar and the text field containing the current time, and these behaviors use the information sent to it to update their own content. The most important thing though, is that you use this information to calculate the average modem speed. That code looks like this:

on updateDownloadInfo me, bytesSoFar, bytesTotal, startTicks

  if startTicks <> 0 and bytesTotal <> 0 then
    tempTime = (the ticks - startTicks) / 60.0
    if tempTime <> 0 then
      modemRate = ((bytesSoFar * 8.0) / 1000.0) / tempTime
      sprite (me.spriteNum).member.text = string (modemRate) && "Kbps"
    end if
  end if

end

This handler starts by making sure that startTicks and bytesTotal are not equal to 0, which effectively makes sure that the download has actually started. Next, it subtracts the current ticks from startTicks and divides the number by 60 to give the exact number of seconds that have elapsed since the download began. If tempTime does not equal zero, then this handler calculates the modemRate by taking the bytes so far, multiplying it by 8, and then dividing it by 1000. It then divides that number by the total number of seconds that have elapsed since the download started and you are left with the actual download speed. Finally, take this number and display it in the text member on screen.

So how did you come up with this formula for modem speed? Well, the number that is sent to the handler is the total number of bytes that have been downloaded. However, conventional modem speeds are represented by bits instead of bytes so you have to multiply the number of bytes by 8 to get the number of bits. Next, modem speeds are referred to in kilobits, or thousands of bits, so to find that number you take the total number of bits and divide them by 1000. Finally, you want to know the number of kilobits per second, so you take the total number of kilobits and divide it by the total number of seconds to get the number of kilobits per seconds.

So when the download is done and you are ready to move on to your Shockwave movie, you have a text field all ready that contains a fairly accurate description of the speed of a user's Internet connection.

A sample movie is available for download in Macintosh or Windows format.

Will Turnage is a multimedia programmer based in New York City. In addition to his weekly role as Director Online's Multimedia Handyman, he is also the Technology Director for Sony Music's Client Side Technologies Group. You can read more about his work at http://will.turnage.com/.

Copyright 1997-2017, Director Online. Article content copyright by respective authors.