Author: SOFTINNOV / Nenad Rakocevic Date: 10/09/2004 Version: 1.1 Comments: nr@softinnov.com
Table of Contents
1. Requirements
2. Description
3. Port operations
3.1. Open
3.2. Insert
3.3. Close
3.4. Query
4. Callbacks
4.1. On-Input
4.2. On-Completed
5. Port properties
5.1. Show-window
5.2. Output
6. Working with Event Loops
7. Simple Example of Integration with View
8. License
This protocol relies on native operating system calls, so the LIBRARY module is required. This module is available in the following REBOL products :
Currently, only the Windows platform is supported. (Support for various Unices may be added in future version)
- REBOL / View / Pro
- REBOL / Command
- REBOL / SDK
This is an asynchronous CALL function implementation. That means that it does the same job as the native CALL command, but allows you to retrieve output data without blocking your REBOL session. Furthermore, you can execute several system calls at the same time while running a View event loop !A simple callback system is provided. It allows you to process output data in a "streamed" way without having to wait for called command to finish.
Usage :
Opens a call port and returns the port. No target needed in the URL.open call://
Usage:
Launch the execution of a command on the given port. The 2nd argument is a STRING! value containing a valid system command (with correct path and argument if needed). If you try to execute a command on a busy port, an error will occur. Once the called command has finished, you can re-use the same opened port to call another command. (beware on resetting correctly the callbacks if required)insert port "system command"Example:
p: open call:// p/locals/on-input: func [...]... insert p "command-1" wait p ; enter an event loop (if you're not using 'view loop) ... p/locals/on-input: func [...]... insert p "command-2" wait p ... close p
Usage:
Closes an opened call port.close port
Usage:
Query a call port for activity. Returns TRUE if the port is busy executing a command, else FALSE.query port
These callbacks can be defined for each new CALL port. It's up to the user to set them to useful functions to be able to process incoming data. They are located in port/locals. You have to set them before using INSERT. By default, these words are set to none value.Example:
port: open call:// port/locals/on-input: func [...][...] port/locals/on-completed: func [...][...] insert port "command" ...
This event is generated each time the port receive some new data from the currently executing command.Prototype:
whereon-input: func [ port [port!] data [string!] ][ ...function body... ]
port is the port generating this event. data a string! value containing the new received data from the executing command.
This event is generated juste once, when the executed command has finished.Prototype:
whereon-completed: func [ port [port!] ][ ...function body... ]
port is the port generating this event.
These properties are located in port/locals object.
This word should be affected to a LOGIC! value. This property have to be set before executing the call using the INSERT function.
TRUE Show the executed command window, if any. FALSE Do not show the window. (This typically affects DOS commands window)
The purpose of this property is to accumulate the executed command ouput data until the end of the execution. This property is available for reading from all callbacks.Example:
p: open call:// p/locals/on-completed: func [port][ print ["Result:" newline port/locals/output] ] insert p "ping www.rebol.com" wait p ... close p
The asynchronous nature of the call:// port requires a running event loop in order to be able to trigger the callbacks. This can be done in different ways :
WAIT The WAIT native can be used to wait on the call:// port or a list of ports. This can be useful to mix call:// port with TCP or UDP asynchronous comunication. DO-EVENTS The DO-EVENTS function is just a shortcut for WAIT [] which waits on the system ports list defined in system/ports/wait-list. You can freely add and remove ports from this list. You have to insert your call:// port in the system ports list VIEW The VIEW function starts an event loop using DO-EVENTS. So in order to allow both View and call:// events, you have to insert your port in the system ports list.
The following example shows how a call:// port can be integrated in a View application.
do %async-call.rcmd-port: open call://append system/ports/wait-list cmd-portcmd-port/locals/on-input: func [port data][ prin data ]The View window and buttons keeps being responsive while the external command is executed. See the "ping demo" script for a more advanced example.view layout [ button 200 "Click me while the command runs" [print "Button works!"] but: button 200 "Traceroute on rebol.com" [ insert cmd-port "tracert rebol.com" ] button "Quit" [ remove system/ports/wait-list cmd-port close cmd-port unview ] ]
Copyright notice:
If you use this library in a product, I would appreciate *not* receiving lengthly legal documents to sign. The sources are provided for free but without warranty of any kind. The call:// library has been entirely written by Nenad Rakocevic; it does not include third-party code.(C) 2004 SOFTINNOV This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Nenad Rakocevic / SOFTINNOV nr@softinnov.comIf you redistribute modified sources, I would appreciate that you include in the call-protocol.r file history information documenting your changes.