From: Anton Rolls
AR> Scott, I think you are a bit negative about transfer rates. :)
AR> Surely there is a way.
...

It was one of those things were as soon as I sent my email, I, too, thought of a way 
to show progress, but our satellite signals times are limited.  My guess is that there 
will already be 3 more ways to do it by the time this arrives!

Not unlike Anton's way in using read, I capture the actual bytes read from the return 
of read-io and accumulate these in a variable.  If the site provides content length, 
then the patch can compare sent to expected.  Unfortunately, not all servers/websites 
send the content length.  

At the end of the http scheme, and the variable "bytes-transferred", as in:
   ...
    cache-size: 5
    user-agent: "REBOL View 1.2.10.3.1"
    bytes-transferred: 0
]

Then change the read function to (watch for line wrap):

        read: func [
            port "An open port spec" 
            data "A buffer to use for the read"
            /local bytes-read
        ][
            net-utils/net-log ["low level read of " port/state/num "bytes"]
            bytes-read: read-io port/sub-port data port/state/num
            bytes-transferred: bytes-transferred + bytes-read
            if port/locals/headers/content-length <> none [print [to-integer 
(bytes-transferred / (to-integer port/locals/headers/content-length) * 100) "percent"]]
            bytes-read
        ]

Reading a page in which the server gives content-length will allow the calculation of 
percent received.  I realized that the read function needs to return the bytes, read, 
hence the last line.

Expanding on the idea, I decided for fun to try to create a visual feedback method 
that gives progress bar when the content-length is known, or simple accumulated bytes 
retrieved, when content-length was unknown.  It requires a fair amount of patching.

Starting with a fresh copy of the http scheme, one first alters the continue-post 
function:

continue-post: func [/tunnel] [
    response-line: system/words/pick port/sub-port 1 
    net-utils/net-log response-line 
    either none? response-line [do error] [
        either none? result: select either tunnel [tunnel-actions] [response-actions] 
        response-code: to-integer second parse response-line none [do error] [do get 
result]
    ]
    if show-progress [
        either port/locals/headers/content-length <> none [
            progress-message/pane: layout/origin/offset [p: progress] 0x0 0x0 
            show progress-message
        ][
            progress-message/pane: layout/origin/offset [t: text 200x16] 0x0 0x0  
            show progress-message
        ]
    ]
] 

Then following the close block and build-port further down, one inserts these lines
...
] 
build-port ;insert following lines
if all [block? port/state/custom post-data: find port/state/custom to-lit-word 
'progress block? post-data] [
    show-progress: true
    progress-message: get to-word select port/state/custom to-lit-word 'progress
]

Then one changes the close function:

close: func [port][
    if show-progress [
        progress-message/pane: layout/origin/offset [t: text 200x16] 0x0 0x0  
        show progress-message
        t/text: "Done!"
        show t
        show-progress: none
    ]
    system/words/close port/sub-port
    bytes-transferred: 0
]

One changes the read function:

read: func [
    port "An open port spec" 
    data "A buffer to use for the read"
    /local bytes-read
][
    net-utils/net-log ["low level read of " port/state/num "bytes"]
    bytes-read: read-io port/sub-port data port/state/num
    bytes-transferred: bytes-transferred + bytes-read
    if show-progress [
        either port/locals/headers/content-length <> none [
            p/data: bytes-transferred / (to-integer port/locals/headers/content-length)
            show p
            ;loop 10000000 [] ;uncomment to see fast pages load
        ][
            t/text: bytes-transferred
            show t
            ;loop 10000000 []
        ]
    ]
    bytes-read
]

Finally, one adds variables to the end of the scheme:
....
    user-agent: "REBOL View 1.2.10.3.1"
    bytes-transferred: 0
    show-progress: progress-message: p: t: none
]

One uses the custom refinement to pass the reference to a VID box:

view layout [
    f: field 300x24
    button "Get Page" [
        read/custom trim to-url f/text ['progress :my-pane]
    ]
    my-pane: box 200x16
    button "Exit" [quit]
]

When one types in a url from a website where the server gives the content-length, the 
box gets a progress bar embedded, which is then updated based on the percentage of 
bytes read.  When the url is served from a server that does not give the 
content-length, then the bytes retrieved are displayed.  After completed, the progress 
box is converted to text that says "Done!"  I have commented out some do nothing loops 
in case your downloads are too fast, and you are trying to see the changes at work.  

I was just about to send this when I received the most recent set of emails, including 
Max's own patch on read-net.  Oh well, it still may prove useful to him or someone 
else in another context and/or to take advantage of all the extra features of the http 
protocol.

--Scott Jones

-- 
To unsubscribe from this list, just send an email to
[EMAIL PROTECTED] with unsubscribe as the subject.

Reply via email to